summaryrefslogtreecommitdiff
path: root/Docs
diff options
context:
space:
mode:
authorbk@work.mysql.com <>2000-07-31 21:29:14 +0200
committerbk@work.mysql.com <>2000-07-31 21:29:14 +0200
commitf4c589ff6c653d1d2a09c26e46ead3c8a15655d8 (patch)
treed253a359142dfc1ed247d5d4365d86972ea31109 /Docs
parent7eec25e393727b16bb916b50d82b0aa3084e065c (diff)
downloadmariadb-git-f4c589ff6c653d1d2a09c26e46ead3c8a15655d8.tar.gz
Import changeset
Diffstat (limited to 'Docs')
-rw-r--r--Docs/.cvsignore40
-rw-r--r--Docs/Attic/myisam.doc901
-rwxr-xr-xDocs/Flags/australia.eps87
-rw-r--r--Docs/Flags/australia.gifbin0 -> 689 bytes
-rwxr-xr-xDocs/Flags/australia.txt0
-rwxr-xr-xDocs/Flags/austria.eps87
-rw-r--r--Docs/Flags/austria.gifbin0 -> 132 bytes
-rwxr-xr-xDocs/Flags/austria.txt0
-rw-r--r--Docs/Flags/brazil.eps87
-rw-r--r--Docs/Flags/brazil.gifbin0 -> 662 bytes
-rw-r--r--Docs/Flags/brazil.txt0
-rw-r--r--Docs/Flags/bulgaria.eps87
-rw-r--r--Docs/Flags/bulgaria.gifbin0 -> 141 bytes
-rw-r--r--Docs/Flags/bulgaria.txt0
-rwxr-xr-xDocs/Flags/canada.eps87
-rw-r--r--Docs/Flags/canada.gifbin0 -> 407 bytes
-rwxr-xr-xDocs/Flags/canada.txt0
-rw-r--r--Docs/Flags/chile.eps87
-rw-r--r--Docs/Flags/chile.gifbin0 -> 370 bytes
-rw-r--r--Docs/Flags/chile.txt0
-rw-r--r--Docs/Flags/china.eps87
-rw-r--r--Docs/Flags/china.gifbin0 -> 224 bytes
-rw-r--r--Docs/Flags/china.txt0
-rw-r--r--Docs/Flags/croatia.eps87
-rw-r--r--Docs/Flags/croatia.gifbin0 -> 659 bytes
-rw-r--r--Docs/Flags/croatia.txt0
-rwxr-xr-xDocs/Flags/czech-republic.eps87
-rw-r--r--Docs/Flags/czech-republic.gifbin0 -> 248 bytes
-rwxr-xr-xDocs/Flags/czech-republic.txt0
-rw-r--r--Docs/Flags/denmark.eps87
-rw-r--r--Docs/Flags/denmark.gifbin0 -> 253 bytes
-rw-r--r--Docs/Flags/denmark.txt0
-rw-r--r--Docs/Flags/estonia.eps87
-rw-r--r--Docs/Flags/estonia.gifbin0 -> 126 bytes
-rw-r--r--Docs/Flags/estonia.txt0
-rw-r--r--Docs/Flags/finland.eps87
-rw-r--r--Docs/Flags/finland.gifbin0 -> 192 bytes
-rw-r--r--Docs/Flags/finland.txt0
-rw-r--r--Docs/Flags/france.eps87
-rw-r--r--Docs/Flags/france.gifbin0 -> 158 bytes
-rw-r--r--Docs/Flags/france.txt0
-rwxr-xr-xDocs/Flags/germany.eps87
-rw-r--r--Docs/Flags/germany.gifbin0 -> 126 bytes
-rwxr-xr-xDocs/Flags/germany.txt0
-rwxr-xr-xDocs/Flags/great-britain.eps87
-rw-r--r--Docs/Flags/great-britain.gifbin0 -> 1193 bytes
-rwxr-xr-xDocs/Flags/great-britain.txt0
-rw-r--r--Docs/Flags/greece.eps87
-rw-r--r--Docs/Flags/greece.gifbin0 -> 282 bytes
-rw-r--r--Docs/Flags/greece.txt0
-rwxr-xr-xDocs/Flags/hungary.eps87
-rw-r--r--Docs/Flags/hungary.gifbin0 -> 141 bytes
-rwxr-xr-xDocs/Flags/hungary.txt0
-rw-r--r--Docs/Flags/iceland.eps87
-rw-r--r--Docs/Flags/iceland.gifbin0 -> 197 bytes
-rw-r--r--Docs/Flags/iceland.txt0
-rw-r--r--Docs/Flags/ireland.eps87
-rw-r--r--Docs/Flags/ireland.gifbin0 -> 158 bytes
-rw-r--r--Docs/Flags/ireland.txt0
-rw-r--r--Docs/Flags/island.eps0
-rw-r--r--Docs/Flags/island.gif0
-rw-r--r--Docs/Flags/island.txt0
-rwxr-xr-xDocs/Flags/israel.eps87
-rw-r--r--Docs/Flags/israel.gifbin0 -> 368 bytes
-rwxr-xr-xDocs/Flags/israel.txt0
-rwxr-xr-xDocs/Flags/italy.eps87
-rw-r--r--Docs/Flags/italy.gifbin0 -> 158 bytes
-rwxr-xr-xDocs/Flags/italy.txt0
-rwxr-xr-xDocs/Flags/japan.eps87
-rw-r--r--Docs/Flags/japan.gifbin0 -> 357 bytes
-rwxr-xr-xDocs/Flags/japan.txt0
-rw-r--r--Docs/Flags/kroatia.eps0
-rw-r--r--Docs/Flags/kroatia.gif0
-rw-r--r--Docs/Flags/kroatia.txt0
-rw-r--r--Docs/Flags/netherlands.eps87
-rw-r--r--Docs/Flags/netherlands.gifbin0 -> 141 bytes
-rw-r--r--Docs/Flags/netherlands.txt0
-rw-r--r--Docs/Flags/poland.eps87
-rw-r--r--Docs/Flags/poland.gifbin0 -> 132 bytes
-rw-r--r--Docs/Flags/poland.txt0
-rw-r--r--Docs/Flags/portugal.eps87
-rw-r--r--Docs/Flags/portugal.gifbin0 -> 633 bytes
-rw-r--r--Docs/Flags/portugal.txt0
-rw-r--r--Docs/Flags/romania.eps87
-rw-r--r--Docs/Flags/romania.gifbin0 -> 158 bytes
-rw-r--r--Docs/Flags/romania.txt0
-rwxr-xr-xDocs/Flags/russia.eps87
-rw-r--r--Docs/Flags/russia.gifbin0 -> 141 bytes
-rwxr-xr-xDocs/Flags/russia.txt0
-rw-r--r--Docs/Flags/singapore.eps87
-rw-r--r--Docs/Flags/singapore.gifbin0 -> 389 bytes
-rw-r--r--Docs/Flags/singapore.txt0
-rw-r--r--Docs/Flags/south-africa.eps87
-rw-r--r--Docs/Flags/south-africa.gifbin0 -> 650 bytes
-rw-r--r--Docs/Flags/south-africa.txt0
-rw-r--r--Docs/Flags/south-africa1.eps87
-rw-r--r--Docs/Flags/south-africa1.gifbin0 -> 650 bytes
-rw-r--r--Docs/Flags/south-africa1.txt0
-rwxr-xr-xDocs/Flags/south-korea.eps87
-rw-r--r--Docs/Flags/south-korea.gifbin0 -> 663 bytes
-rwxr-xr-xDocs/Flags/south-korea.txt0
-rw-r--r--Docs/Flags/spain.eps87
-rw-r--r--Docs/Flags/spain.gifbin0 -> 138 bytes
-rw-r--r--Docs/Flags/spain.txt0
-rwxr-xr-xDocs/Flags/sweden.eps87
-rw-r--r--Docs/Flags/sweden.gifbin0 -> 193 bytes
-rwxr-xr-xDocs/Flags/sweden.txt0
-rw-r--r--Docs/Flags/switzerland.eps87
-rw-r--r--Docs/Flags/switzerland.gifbin0 -> 237 bytes
-rw-r--r--Docs/Flags/switzerland.txt0
-rwxr-xr-xDocs/Flags/taiwan.eps87
-rw-r--r--Docs/Flags/taiwan.gifbin0 -> 377 bytes
-rwxr-xr-xDocs/Flags/taiwan.txt0
-rw-r--r--Docs/Flags/ukraine.eps87
-rw-r--r--Docs/Flags/ukraine.gifbin0 -> 132 bytes
-rw-r--r--Docs/Flags/ukraine.txt0
-rwxr-xr-xDocs/Flags/usa.eps87
-rw-r--r--Docs/Flags/usa.gifbin0 -> 731 bytes
-rwxr-xr-xDocs/Flags/usa.txt0
-rw-r--r--Docs/Images/Attic/html-fs.gifbin0 -> 3349 bytes
-rw-r--r--Docs/Images/Attic/mysql-01.gifbin0 -> 4097 bytes
-rw-r--r--Docs/Images/Attic/mysql-02.gifbin0 -> 4811 bytes
-rw-r--r--Docs/Images/Attic/mysql-03.gifbin0 -> 716 bytes
-rw-r--r--Docs/Images/Attic/mysql-04.gifbin0 -> 909 bytes
-rw-r--r--Docs/Images/Attic/mysql-05.gifbin0 -> 2192 bytes
-rw-r--r--Docs/Images/Attic/mysql-06.gifbin0 -> 3082 bytes
-rw-r--r--Docs/Images/Attic/mysql-07.gifbin0 -> 4209 bytes
-rw-r--r--Docs/Images/Attic/mysql-08.gifbin0 -> 1595 bytes
-rw-r--r--Docs/Images/Attic/mysql-09.gifbin0 -> 2627 bytes
-rw-r--r--Docs/Images/Attic/mysql-10.gifbin0 -> 2455 bytes
-rw-r--r--Docs/Images/Attic/mysql-11.gifbin0 -> 1436 bytes
-rw-r--r--Docs/Images/Attic/mysql-12.gifbin0 -> 2642 bytes
-rw-r--r--Docs/Images/Attic/mysql-13.gifbin0 -> 2914 bytes
-rw-r--r--Docs/Images/Attic/mysql-14.gifbin0 -> 2686 bytes
-rw-r--r--Docs/Images/Attic/mysql-15.gifbin0 -> 2310 bytes
-rw-r--r--Docs/Images/Attic/mysql-16.gifbin0 -> 19192 bytes
-rw-r--r--Docs/Images/Attic/mysql-17.gifbin0 -> 2059 bytes
-rw-r--r--Docs/Images/Attic/mysql-18.gifbin0 -> 918 bytes
-rw-r--r--Docs/Images/Attic/mysql-19.gifbin0 -> 2607 bytes
-rw-r--r--Docs/Images/Attic/mysql-compatible.jpgbin0 -> 2809 bytes
-rw-r--r--Docs/Images/Attic/mysql5.gifbin0 -> 2192 bytes
-rw-r--r--Docs/Images/Attic/mysql_anim-01.gifbin0 -> 15008 bytes
-rw-r--r--Docs/Images/Attic/mysql_anim-02.gifbin0 -> 21236 bytes
-rw-r--r--Docs/Images/Attic/mysql_anim-03.gifbin0 -> 16958 bytes
-rw-r--r--Docs/Images/Attic/mysql_anim-04.gifbin0 -> 12716 bytes
-rw-r--r--Docs/Images/Attic/mysql_anim-05.gifbin0 -> 22962 bytes
-rw-r--r--Docs/Images/Attic/mysql_anim-06.gifbin0 -> 42606 bytes
-rw-r--r--Docs/Images/Attic/powered-by-MySQL-transparent.gifbin0 -> 4209 bytes
-rw-r--r--Docs/Images/empty.pngbin0 -> 108 bytes
-rwxr-xr-xDocs/Images/flag-background.pnmbin0 -> 2170 bytes
-rw-r--r--Docs/Images/mysql-logo.gifbin0 -> 3082 bytes
-rw-r--r--Docs/LICENSE98
-rw-r--r--Docs/Makefile.am120
-rw-r--r--Docs/MySQL-logos/mysql-01.gifbin0 -> 4097 bytes
-rw-r--r--Docs/MySQL-logos/mysql-02.gifbin0 -> 4811 bytes
-rw-r--r--Docs/MySQL-logos/mysql-03.gifbin0 -> 716 bytes
-rw-r--r--Docs/MySQL-logos/mysql-04.gifbin0 -> 909 bytes
-rw-r--r--Docs/MySQL-logos/mysql-05.gifbin0 -> 2192 bytes
-rw-r--r--Docs/MySQL-logos/mysql-06.gifbin0 -> 3082 bytes
-rw-r--r--Docs/MySQL-logos/mysql-07.gifbin0 -> 4209 bytes
-rw-r--r--Docs/MySQL-logos/mysql-08.gifbin0 -> 1595 bytes
-rw-r--r--Docs/MySQL-logos/mysql-09.gifbin0 -> 2627 bytes
-rw-r--r--Docs/MySQL-logos/mysql-10.gifbin0 -> 2455 bytes
-rw-r--r--Docs/MySQL-logos/mysql-11.gifbin0 -> 1436 bytes
-rw-r--r--Docs/MySQL-logos/mysql-12.gifbin0 -> 2642 bytes
-rw-r--r--Docs/MySQL-logos/mysql-13.gifbin0 -> 2914 bytes
-rw-r--r--Docs/MySQL-logos/mysql-14.gifbin0 -> 2686 bytes
-rw-r--r--Docs/MySQL-logos/mysql-15.gifbin0 -> 2310 bytes
-rw-r--r--Docs/MySQL-logos/mysql-16.gifbin0 -> 19192 bytes
-rw-r--r--Docs/MySQL-logos/mysql-17.gifbin0 -> 2059 bytes
-rw-r--r--Docs/MySQL-logos/mysql-compatible.jpgbin0 -> 2809 bytes
-rw-r--r--Docs/MySQL-logos/mysql_anim-01.gifbin0 -> 15008 bytes
-rw-r--r--Docs/MySQL-logos/mysql_anim-02.gifbin0 -> 21236 bytes
-rw-r--r--Docs/MySQL-logos/mysql_anim-03.gifbin0 -> 16958 bytes
-rw-r--r--Docs/MySQL-logos/mysql_anim-04.gifbin0 -> 12716 bytes
-rw-r--r--Docs/MySQL-logos/mysql_anim-05.gifbin0 -> 22962 bytes
-rw-r--r--Docs/MySQL-logos/mysql_anim-06.gifbin0 -> 42606 bytes
-rw-r--r--Docs/Raw-Flags/afghanistan.gifbin0 -> 11155 bytes
-rw-r--r--Docs/Raw-Flags/albania.gifbin0 -> 8288 bytes
-rw-r--r--Docs/Raw-Flags/algeria.gifbin0 -> 5003 bytes
-rw-r--r--Docs/Raw-Flags/andorra.gifbin0 -> 21227 bytes
-rw-r--r--Docs/Raw-Flags/angola.gifbin0 -> 4836 bytes
-rw-r--r--Docs/Raw-Flags/antartica.gifbin0 -> 3185 bytes
-rw-r--r--Docs/Raw-Flags/antigua-and-barbuda.gifbin0 -> 5239 bytes
-rw-r--r--Docs/Raw-Flags/argentina.gifbin0 -> 5242 bytes
-rw-r--r--Docs/Raw-Flags/armenia.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/australia.gifbin0 -> 6493 bytes
-rw-r--r--Docs/Raw-Flags/austria.gifbin0 -> 1232 bytes
-rw-r--r--Docs/Raw-Flags/azerbaijan.gifbin0 -> 2931 bytes
-rw-r--r--Docs/Raw-Flags/bahamas.gifbin0 -> 2836 bytes
-rw-r--r--Docs/Raw-Flags/bahrein.gifbin0 -> 2380 bytes
-rw-r--r--Docs/Raw-Flags/bangladesh.gifbin0 -> 2505 bytes
-rw-r--r--Docs/Raw-Flags/barbados.gifbin0 -> 3178 bytes
-rw-r--r--Docs/Raw-Flags/belarus.gifbin0 -> 1232 bytes
-rw-r--r--Docs/Raw-Flags/belgium.gifbin0 -> 2525 bytes
-rw-r--r--Docs/Raw-Flags/belize.gifbin0 -> 28546 bytes
-rw-r--r--Docs/Raw-Flags/benin.gifbin0 -> 2107 bytes
-rw-r--r--Docs/Raw-Flags/bermuda.gifbin0 -> 4278 bytes
-rw-r--r--Docs/Raw-Flags/bhutan.gifbin0 -> 40300 bytes
-rw-r--r--Docs/Raw-Flags/bolivia.gifbin0 -> 11912 bytes
-rw-r--r--Docs/Raw-Flags/bosnia-and-herzegovina.gifbin0 -> 4143 bytes
-rw-r--r--Docs/Raw-Flags/botswana.gifbin0 -> 1451 bytes
-rw-r--r--Docs/Raw-Flags/brazil.gifbin0 -> 6650 bytes
-rw-r--r--Docs/Raw-Flags/brunei.gifbin0 -> 29444 bytes
-rw-r--r--Docs/Raw-Flags/bulgaria.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/burkina-faso.gifbin0 -> 2691 bytes
-rw-r--r--Docs/Raw-Flags/burma.gifbin0 -> 11558 bytes
-rw-r--r--Docs/Raw-Flags/burundi.gifbin0 -> 6742 bytes
-rw-r--r--Docs/Raw-Flags/cambodia.gifbin0 -> 12976 bytes
-rw-r--r--Docs/Raw-Flags/cameroon.gifbin0 -> 3531 bytes
-rw-r--r--Docs/Raw-Flags/canada.gifbin0 -> 3984 bytes
-rw-r--r--Docs/Raw-Flags/cape-verde.gifbin0 -> 3504 bytes
-rw-r--r--Docs/Raw-Flags/central-african-republic.gifbin0 -> 3769 bytes
-rw-r--r--Docs/Raw-Flags/chad.gifbin0 -> 2525 bytes
-rw-r--r--Docs/Raw-Flags/chile.gifbin0 -> 2890 bytes
-rw-r--r--Docs/Raw-Flags/china.gifbin0 -> 2054 bytes
-rw-r--r--Docs/Raw-Flags/colombia.gifbin0 -> 1531 bytes
-rw-r--r--Docs/Raw-Flags/comoros.gifbin0 -> 3049 bytes
-rw-r--r--Docs/Raw-Flags/congo.gifbin0 -> 3265 bytes
-rw-r--r--Docs/Raw-Flags/costa-rica.gifbin0 -> 1620 bytes
-rw-r--r--Docs/Raw-Flags/cote-d-ivoire.gifbin0 -> 2525 bytes
-rw-r--r--Docs/Raw-Flags/croatia.gifbin0 -> 13740 bytes
-rw-r--r--Docs/Raw-Flags/cuba.gifbin0 -> 3986 bytes
-rw-r--r--Docs/Raw-Flags/cyprus.gifbin0 -> 3929 bytes
-rw-r--r--Docs/Raw-Flags/czech-republic.gifbin0 -> 2726 bytes
-rw-r--r--Docs/Raw-Flags/denmark-original-incorrect.gifbin0 -> 1893 bytes
-rw-r--r--Docs/Raw-Flags/denmark.gifbin0 -> 13718 bytes
-rw-r--r--Docs/Raw-Flags/djibouti.gifbin0 -> 3462 bytes
-rw-r--r--Docs/Raw-Flags/dominica.gifbin0 -> 14390 bytes
-rw-r--r--Docs/Raw-Flags/dominican-republic.gifbin0 -> 8432 bytes
-rw-r--r--Docs/Raw-Flags/ecuador.gifbin0 -> 18692 bytes
-rw-r--r--Docs/Raw-Flags/egypt.gifbin0 -> 8423 bytes
-rw-r--r--Docs/Raw-Flags/el-salvador.gifbin0 -> 12073 bytes
-rw-r--r--Docs/Raw-Flags/equatorial-guinea.gifbin0 -> 8884 bytes
-rw-r--r--Docs/Raw-Flags/eritrea.gifbin0 -> 8154 bytes
-rw-r--r--Docs/Raw-Flags/estonia.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/ethiopia.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/fiji.gifbin0 -> 17779 bytes
-rw-r--r--Docs/Raw-Flags/finland.gifbin0 -> 1812 bytes
-rw-r--r--Docs/Raw-Flags/france.gifbin0 -> 2525 bytes
-rw-r--r--Docs/Raw-Flags/gabon.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/gambia.gifbin0 -> 1831 bytes
-rw-r--r--Docs/Raw-Flags/georgia.gifbin0 -> 1900 bytes
-rw-r--r--Docs/Raw-Flags/germany.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/ghana.gifbin0 -> 2394 bytes
-rw-r--r--Docs/Raw-Flags/great-britain.gifbin0 -> 8165 bytes
-rw-r--r--Docs/Raw-Flags/greece.gifbin0 -> 2173 bytes
-rw-r--r--Docs/Raw-Flags/greenland.gifbin0 -> 2612 bytes
-rw-r--r--Docs/Raw-Flags/grenada.gifbin0 -> 6780 bytes
-rw-r--r--Docs/Raw-Flags/guatemala.gifbin0 -> 19048 bytes
-rw-r--r--Docs/Raw-Flags/guinea-bissau.gifbin0 -> 3300 bytes
-rw-r--r--Docs/Raw-Flags/guinea.gifbin0 -> 2525 bytes
-rw-r--r--Docs/Raw-Flags/guyana.gifbin0 -> 5299 bytes
-rw-r--r--Docs/Raw-Flags/haiti.gifbin0 -> 24028 bytes
-rw-r--r--Docs/Raw-Flags/honduras.gifbin0 -> 2223 bytes
-rw-r--r--Docs/Raw-Flags/hungary.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/iceland.gifbin0 -> 2544 bytes
-rw-r--r--Docs/Raw-Flags/india.gifbin0 -> 4399 bytes
-rw-r--r--Docs/Raw-Flags/indonesia.gifbin0 -> 1205 bytes
-rw-r--r--Docs/Raw-Flags/iran.gifbin0 -> 7703 bytes
-rw-r--r--Docs/Raw-Flags/iraq.gifbin0 -> 4538 bytes
-rw-r--r--Docs/Raw-Flags/ireland.gifbin0 -> 2525 bytes
-rw-r--r--Docs/Raw-Flags/israel.gifbin0 -> 2808 bytes
-rw-r--r--Docs/Raw-Flags/italy.gifbin0 -> 2525 bytes
-rw-r--r--Docs/Raw-Flags/jamaica.gifbin0 -> 4749 bytes
-rw-r--r--Docs/Raw-Flags/japan.gifbin0 -> 2505 bytes
-rw-r--r--Docs/Raw-Flags/jordan.gifbin0 -> 3755 bytes
-rw-r--r--Docs/Raw-Flags/kazakhstan.gifbin0 -> 24988 bytes
-rw-r--r--Docs/Raw-Flags/kenya.gifbin0 -> 6806 bytes
-rw-r--r--Docs/Raw-Flags/kiribati.gifbin0 -> 9341 bytes
-rw-r--r--Docs/Raw-Flags/kuwait.gifbin0 -> 2926 bytes
-rw-r--r--Docs/Raw-Flags/kyrgyzstan.gifbin0 -> 7742 bytes
-rw-r--r--Docs/Raw-Flags/laos.gifbin0 -> 2402 bytes
-rw-r--r--Docs/Raw-Flags/latvia.gifbin0 -> 1142 bytes
-rw-r--r--Docs/Raw-Flags/lebanon.gifbin0 -> 2874 bytes
-rw-r--r--Docs/Raw-Flags/lesotho.gifbin0 -> 5568 bytes
-rw-r--r--Docs/Raw-Flags/liberia.gifbin0 -> 2889 bytes
-rw-r--r--Docs/Raw-Flags/libya.gifbin0 -> 787 bytes
-rw-r--r--Docs/Raw-Flags/liechtenstein.gifbin0 -> 9832 bytes
-rw-r--r--Docs/Raw-Flags/lithuania.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/luxembourg.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/macedonia.gifbin0 -> 6907 bytes
-rw-r--r--Docs/Raw-Flags/madagascar.gifbin0 -> 2061 bytes
-rw-r--r--Docs/Raw-Flags/malawi.gifbin0 -> 5622 bytes
-rw-r--r--Docs/Raw-Flags/malaysia.gifbin0 -> 4621 bytes
-rw-r--r--Docs/Raw-Flags/maldives.gifbin0 -> 2623 bytes
-rw-r--r--Docs/Raw-Flags/mali.gifbin0 -> 2525 bytes
-rw-r--r--Docs/Raw-Flags/malta.gifbin0 -> 7209 bytes
-rw-r--r--Docs/Raw-Flags/marshall.gifbin0 -> 6614 bytes
-rw-r--r--Docs/Raw-Flags/mauritania.gifbin0 -> 2511 bytes
-rw-r--r--Docs/Raw-Flags/mauritius.gifbin0 -> 1888 bytes
-rw-r--r--Docs/Raw-Flags/mexico.gifbin0 -> 16889 bytes
-rw-r--r--Docs/Raw-Flags/micronesia.gifbin0 -> 3092 bytes
-rw-r--r--Docs/Raw-Flags/moldova.gifbin0 -> 16586 bytes
-rw-r--r--Docs/Raw-Flags/monaco.gifbin0 -> 1205 bytes
-rw-r--r--Docs/Raw-Flags/mongolia.gifbin0 -> 5532 bytes
-rw-r--r--Docs/Raw-Flags/morocco.gifbin0 -> 4507 bytes
-rw-r--r--Docs/Raw-Flags/mozambique.gifbin0 -> 9086 bytes
-rw-r--r--Docs/Raw-Flags/namibia.gifbin0 -> 6725 bytes
-rw-r--r--Docs/Raw-Flags/nauru.gifbin0 -> 2209 bytes
-rw-r--r--Docs/Raw-Flags/nepal.gifbin0 -> 5658 bytes
-rw-r--r--Docs/Raw-Flags/netherlands.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/new-zealand.gifbin0 -> 7248 bytes
-rw-r--r--Docs/Raw-Flags/nicaragua.gifbin0 -> 8024 bytes
-rw-r--r--Docs/Raw-Flags/niger.gifbin0 -> 2381 bytes
-rw-r--r--Docs/Raw-Flags/nigeria.gifbin0 -> 1998 bytes
-rw-r--r--Docs/Raw-Flags/north-korea.gifbin0 -> 3044 bytes
-rw-r--r--Docs/Raw-Flags/norway.gifbin0 -> 2544 bytes
-rw-r--r--Docs/Raw-Flags/oman.gifbin0 -> 6957 bytes
-rw-r--r--Docs/Raw-Flags/pakistan.gifbin0 -> 3805 bytes
-rw-r--r--Docs/Raw-Flags/panama.gifbin0 -> 4459 bytes
-rw-r--r--Docs/Raw-Flags/papua-new-guinea.gifbin0 -> 5742 bytes
-rw-r--r--Docs/Raw-Flags/paraguay.gifbin0 -> 8733 bytes
-rw-r--r--Docs/Raw-Flags/peru.gifbin0 -> 14338 bytes
-rw-r--r--Docs/Raw-Flags/philippines.gifbin0 -> 7606 bytes
-rw-r--r--Docs/Raw-Flags/poland.gifbin0 -> 1205 bytes
-rw-r--r--Docs/Raw-Flags/portugal.gifbin0 -> 11287 bytes
-rw-r--r--Docs/Raw-Flags/qatar.gifbin0 -> 2380 bytes
-rw-r--r--Docs/Raw-Flags/romania.gifbin0 -> 2777 bytes
-rw-r--r--Docs/Raw-Flags/russia.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/rwanda.gifbin0 -> 3844 bytes
-rw-r--r--Docs/Raw-Flags/saint-kitts-and-nevis.gifbin0 -> 6152 bytes
-rw-r--r--Docs/Raw-Flags/saint-lucia.gifbin0 -> 4434 bytes
-rw-r--r--Docs/Raw-Flags/samoa.gifbin0 -> 2219 bytes
-rw-r--r--Docs/Raw-Flags/sao-tome-and-principe.gifbin0 -> 3978 bytes
-rw-r--r--Docs/Raw-Flags/saudi-arabia.gifbin0 -> 18855 bytes
-rw-r--r--Docs/Raw-Flags/senegal.gifbin0 -> 3532 bytes
-rw-r--r--Docs/Raw-Flags/seychelles.gifbin0 -> 3408 bytes
-rw-r--r--Docs/Raw-Flags/sierra-leone.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/singapore.gifbin0 -> 3207 bytes
-rw-r--r--Docs/Raw-Flags/slovakia.gifbin0 -> 4706 bytes
-rw-r--r--Docs/Raw-Flags/slovenia.gifbin0 -> 5351 bytes
-rw-r--r--Docs/Raw-Flags/solomon-islands.gifbin0 -> 4369 bytes
-rw-r--r--Docs/Raw-Flags/somalia.gifbin0 -> 2010 bytes
-rw-r--r--Docs/Raw-Flags/south-africa.gifbin0 -> 5116 bytes
-rw-r--r--Docs/Raw-Flags/south-korea.gifbin0 -> 6838 bytes
-rw-r--r--Docs/Raw-Flags/spain.gifbin0 -> 1252 bytes
-rw-r--r--Docs/Raw-Flags/sri-lanka.gifbin0 -> 14789 bytes
-rw-r--r--Docs/Raw-Flags/sudan.gifbin0 -> 3124 bytes
-rw-r--r--Docs/Raw-Flags/suriname.gifbin0 -> 2499 bytes
-rw-r--r--Docs/Raw-Flags/swaziland.gifbin0 -> 11362 bytes
-rw-r--r--Docs/Raw-Flags/sweden.gifbin0 -> 1812 bytes
-rw-r--r--Docs/Raw-Flags/sweden2.gifbin0 -> 1813 bytes
-rw-r--r--Docs/Raw-Flags/switzerland.gifbin0 -> 1632 bytes
-rw-r--r--Docs/Raw-Flags/syria.gifbin0 -> 2748 bytes
-rw-r--r--Docs/Raw-Flags/taiwan.gifbin0 -> 3866 bytes
-rw-r--r--Docs/Raw-Flags/tajikistan.gifbin0 -> 6245 bytes
-rw-r--r--Docs/Raw-Flags/tanzania.gifbin0 -> 4673 bytes
-rw-r--r--Docs/Raw-Flags/thailand.gifbin0 -> 1620 bytes
-rw-r--r--Docs/Raw-Flags/togo.gifbin0 -> 2815 bytes
-rw-r--r--Docs/Raw-Flags/tonga.gifbin0 -> 2066 bytes
-rw-r--r--Docs/Raw-Flags/trinidad-and-tobago.gifbin0 -> 2807 bytes
-rw-r--r--Docs/Raw-Flags/tunisia.gifbin0 -> 3881 bytes
-rw-r--r--Docs/Raw-Flags/turkey.gifbin0 -> 2557 bytes
-rw-r--r--Docs/Raw-Flags/turkmenistan.gifbin0 -> 26835 bytes
-rw-r--r--Docs/Raw-Flags/tuvalu.gifbin0 -> 7855 bytes
-rw-r--r--Docs/Raw-Flags/uganda.gifbin0 -> 5970 bytes
-rw-r--r--Docs/Raw-Flags/ukraine.gifbin0 -> 1205 bytes
-rw-r--r--Docs/Raw-Flags/united-arab-emirates.gifbin0 -> 2493 bytes
-rw-r--r--Docs/Raw-Flags/united-states-of-america.gifbin0 -> 6528 bytes
-rw-r--r--Docs/Raw-Flags/uruguay.gifbin0 -> 8709 bytes
-rw-r--r--Docs/Raw-Flags/usa.gifbin0 -> 6528 bytes
-rw-r--r--Docs/Raw-Flags/uzbekistan.gifbin0 -> 3968 bytes
-rw-r--r--Docs/Raw-Flags/vanuatu.gifbin0 -> 8928 bytes
-rw-r--r--Docs/Raw-Flags/venezuela.gifbin0 -> 10305 bytes
-rw-r--r--Docs/Raw-Flags/vietnam.gifbin0 -> 2010 bytes
-rw-r--r--Docs/Raw-Flags/vincent-and-grenadines.gifbin0 -> 4234 bytes
-rw-r--r--Docs/Raw-Flags/yemen.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/yugoslavia.gifbin0 -> 1553 bytes
-rw-r--r--Docs/Raw-Flags/zaire.gifbin0 -> 12709 bytes
-rw-r--r--Docs/Raw-Flags/zambia.gifbin0 -> 8598 bytes
-rw-r--r--Docs/Raw-Flags/zimbabwe.gifbin0 -> 10738 bytes
-rw-r--r--Docs/Support/.cvsignore2
-rwxr-xr-xDocs/Support/generate-flag-images37
-rwxr-xr-xDocs/Support/generate-mirror-listing.pl27
-rwxr-xr-xDocs/Support/generate-text-files.pl40
-rwxr-xr-xDocs/Support/make-makefile7
-rwxr-xr-xDocs/Support/texi2html2251
-rw-r--r--Docs/Support/texinfo.tex5868
-rw-r--r--Docs/To-be-included-in-the-manual/MySQL-for-dummies271
-rw-r--r--Docs/Translations/myodbc-br.texi272
-rw-r--r--Docs/Tutorial-MySQL-final.txt1643
-rw-r--r--Docs/internals.texi134
-rw-r--r--Docs/manual-license-spanish.texi709
-rw-r--r--Docs/manual.texi41455
-rw-r--r--Docs/myisam.txt901
-rw-r--r--Docs/mysqld_error.txt355
-rw-r--r--Docs/net_doc.txt944
388 files changed, 59294 insertions, 0 deletions
diff --git a/Docs/.cvsignore b/Docs/.cvsignore
new file mode 100644
index 00000000000..777efb1eb7b
--- /dev/null
+++ b/Docs/.cvsignore
@@ -0,0 +1,40 @@
+COPYING
+COPYING.LIB
+INSTALL-BINARY
+Makefile
+Makefile.in
+Manual-updates
+before-gpl-changes-manual.texi
+include.texi
+manual-before-gpl.texi
+manual-tmp.aux
+manual-tmp.cp
+manual-tmp.fn
+manual-tmp.ky
+manual-tmp.log
+manual-tmp.pdf
+manual-tmp.pg
+manual-tmp.texi
+manual-tmp.toc
+manual-tmp.tp
+manual-tmp.vr
+manual.aux
+manual.cp
+manual.cps
+manual.fn
+manual.fns
+manual.html
+manual.ky
+manual.log
+manual.pdf
+manual.pg
+manual.toc
+manual.tp
+manual.txt
+manual.vr
+manual_a4.ps
+manual_a4.ps.gz
+manual_letter.ps
+manual_letter.ps.gz
+manual_toc.html
+mysql.info
diff --git a/Docs/Attic/myisam.doc b/Docs/Attic/myisam.doc
new file mode 100644
index 00000000000..e0b56e79548
--- /dev/null
+++ b/Docs/Attic/myisam.doc
@@ -0,0 +1,901 @@
+#.# mi_changed()
+
+int mi_is_changed(MI_INFO *mip)
+
+#.#.1 Description
+
+Reports whether any changes have occurred to the MyISAM table associated with mip.
+
+For information only, I notice that mi_changed() is a wrapper around this: (_mi_readinfo(info,F_RDLCK,1)).
+
+#.#.2 Return values
+
+Zero if the table has not changed. Non-zero (-1) if the table has changed.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+if( mi_changed( mip )) printf( "file has changed" );
+====================
+#.# mi_close()
+
+int mi_close( MI_INFO *mip )
+
+#.#.1 Description
+
+Closes the MyISAM table associated with mip, a structure created by mi_open().
+Any locks on that file pointer are released.
+The MI_INFO structure mip is released.
+See also mi_panic() which can be used to close all open MyISAM files.
+mip is a pointer to the MI_INFO returned by mi_open().
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+result = mi_close(mip);
+====================
+#.# mi_create()
+
+int mi_create( const char *name, uint keys, MI_KEYDEF *keydefs,
+ uint columns, MI_COLUMNDEF *recinfo,
+ uint uniques, MI_UNIQUEDEF *uniquedefs,
+ MI_CREATE_INFO *ci, uint flags )
+
+#.#.1 Description
+
+Creates a new MyISAM table.
+Documentation for this function is not complete because I am not using mi_create directly.
+Because all our tables are used with MySQL, I create new tables using SQL "CREATE TABLE" via the C API.
+See MySQL Appendix B "Choosing a table type".
+MyISAM allows about 32 indexes. However the official MySQL limit is 16 until MySQL 4.0.
+
+The parameters are specified as follows:
+name The file pathname, excluding the suffixes.
+keys Number of indexes.
+keydefs A MI_KEYDEF structure containing key definitions.
+HA_KEYTYPE_END=0
+HA_KEYTYPE_TEXT=1, /* Key is sorted as letters */
+HA_KEYTYPE_BINARY=2, /* Key is sorted as unsigned chars
+HA_KEYTYPE_SHORT_INT=3,
+HA_KEYTYPE_LONG_INT=4,
+HA_KEYTYPE_FLOAT=5,
+HA_KEYTYPE_DOUBLE=6,
+HA_KEYTYPE_NUM=7, /* Not packed num with pre-space *
+HA_KEYTYPE_USHORT_INT=8,
+HA_KEYTYPE_ULONG_INT=9,
+HA_KEYTYPE_LONGLONG=10,
+HA_KEYTYPE_ULONGLONG=11,
+HA_KEYTYPE_INT24=12,
+HA_KEYTYPE_UINT24=13,
+HA_KEYTYPE_INT8=14,
+HA_KEYTYPE_VARTEXT=15, /* Key is sorted as letters */
+HA_KEYTYPE_VARBINARY=16 /* Key is sorted as unsigned chars
+columns The number of columns.
+recinfo A MI_COLUMNDEF structure containing column definitions.
+uniques The number of unique indexes.
+uniquedefs A MI_UNIQUEDEF structure containing unique index definitions.
+ci A MI_CREATE_INFO structure containing column definitions.
+flags a pointer to the record buffer that will contain the row.
+
+#.#.2 Return values
+
+Zero if the create is successful. Non-zero if an error occurs.
+
+#.#.3 Errors
+
+HA_WRONG_CREATE_OPTION
+ means that some of the arguments was wrong.
+appart from the above one can get any unix error that one can get from open(), write() or close().
+
+#.#.4 Examples
+
+if (mi_create(fn_format(name,filename,"",MI_NAME_IEXT, 4+ (opt_follow_links ? 16 : 0)),
+ share.base.keys - share.state.header.uniques, keyinfo, share.base.fields, recdef,
+ share.state.header.uniques, uniquedef, &create_info, HA_DONT_TOUCH_DATA))
+====================
+#.# mi_delete()
+
+int mi_delete(MI_INFO *mip, const byte *buf)
+
+#.#.1 Description
+
+Removes a row from a MyISAM table.
+
+mip is an MI_INFO pointer to the open handle.
+buf is the buffer containing the row that is to be deleted.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+EACCES
+File was opened read-only.
+HA_ERR_KEY_NOT_FOUND
+No database read
+HA_ERR_RECORD_CHANGED
+The buffer contents were different to the actual row contents.
+HA_ERR_CRASHED
+The indexing has crashed.
+
+#.#.4 Examples
+
+if (mi_delete(file,read_record))
+====================
+#.# mi_delete_all()
+
+int mi_delete_all_rows(MI_INFO *mip)
+#.#.1 Description
+
+Removes ALL rows from a MyISAM table.
+This only clears the status information. The files are not truncated.
+
+mip is an MI_INFO pointer to the open handle.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+EACCES
+File was opened read-only.
+
+#.#.4 Examples
+
+error = mi_delete_all( mip );
+====================
+#.# mi_extra()
+
+int mi_extra(MI_INFO *info, enum ha_extra_function function)
+
+#.#.1 Description
+
+Controls some special MyISAM modes.
+
+The function parameter can be:
+ HA_EXTRA_NORMAL=0 Optimize for space (def)
+HA_EXTRA_QUICK=1 Optimize for speed
+HA_EXTRA_RESET=2 Reset database to after open
+HA_EXTRA_CACHE=3 Cash record in HA_rrnd()
+HA_EXTRA_NO_CACHE=4 End cacheing of records (def)
+HA_EXTRA_NO_READCHECK=5 No readcheck on update
+HA_EXTRA_READCHECK=6 Use readcheck (def)
+HA_EXTRA_KEYREAD=7 Read only key to database
+HA_EXTRA_NO_KEYREAD=8 Normal read of records (def)
+HA_EXTRA_NO_USER_CHANGE=9 No user is allowed to write
+HA_EXTRA_KEY_CACHE=10
+HA_EXTRA_NO_KEY_CACHE=11
+HA_EXTRA_WAIT_LOCK=12 Wait until file is avalably (def)
+HA_EXTRA_NO_WAIT_LOCK=13 If file is locked, return quickly
+HA_EXTRA_WRITE_CACHE=14 Use write cache in ha_write()
+HA_EXTRA_FLUSH_CACHE=15 flush write_record_cache
+HA_EXTRA_NO_KEYS=16 Remove all update of keys
+HA_EXTRA_KEYREAD_CHANGE_POS=17 Keyread, but change pos
+xxxxchk -r must be used
+HA_EXTRA_REMEMBER_POS=18 Remember pos for next/prev
+HA_EXTRA_RESTORE_POS=19
+HA_EXTRA_REINIT_CACHE=20 init cache from current record
+HA_EXTRA_FORCE_REOPEN=21 Datafile have changed on disk
+HA_EXTRA_FLUSH Flush tables to disk
+HA_EXTRA_NO_ROWS Don't write rows
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+====================
+#.# mi_make_application_key()
+
+void mi_make_application_key(register MI_INFO *mip, uint keynr, uchar *key, const byte *record)
+
+#.#.1 Description
+
+Construct a key string for the given index, from the provided record buffer.
+Monty wrote this function to: "to create an external key for an application from your record. It should work for all keys except BLOB and true VARCHAR (not supported by MySQL yet), but I don't think you have either of these!" He just wrote it, so I expect it to included in releases from about 3.23.15. ??
+
+The parameters are:
+A MI_INFO pointer mip.
+The index number keynr.
+The buffer to contain the formatted key string key.
+The record buffer record.
+
+#.#.2 Return values
+
+The byte length of the created key string.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+uint new_length=_mi_make_application_key(info,i,new_key,newrec);
+====================
+#.# mi_open()
+
+MI_INFO *mi_open( const char *name, int mode, uint handle_locking )
+
+#.#.1 Description
+
+Opens a MyISAM file for processing.
+mi_open() returns a MI_INFO structure pointer that you must use in subsequent operations on the MyISAM file. MI_INFO structures are defined in "myisam/myisamdef.h", which is included in your program via your include myisam.h - used by both MyISAM and MySQL.
+The name parameter must contain a null-terminated string without an extension, which is the filename of the MyISAM file to be processed.
+There is no automatic positioning nor key selection.
+Caution! It is extremely important to close MyISAM files after processing has finished, especially on operating systems without file-locking system calls. Failure to close MyISAM files using mi_close() or mi_panic() leaves the files locked on systems without these system calls.
+
+name Is the name of the file.
+mode Is the access mode parameter. Use one of the following access mode parameters:
+O_RDONLY to open for input only.
+O_RDWR opens the file for output.
+O_SHARE opens the file for both input and output. When used, O_SHARE should be added to O_RDONLY and O_RDWR.
+handle_locking is the locking mode parameter. Select from the following:
+HA_OPEN_ABORT_IF_LOCKED (0) exit with error if database is locked
+HA_OPEN_WAIT_IF_LOCKED (1) wait if database is locked
+HA_OPEN_IGNORE_IF_LOCKED (2) continue, but count-vars in st_i_info may be wrong. count-vars are automatically fixed after next isam request.
+
+#.#.2 Return values
+
+A pointer to MI_INFO for successfully open file. NULL if unsuccessful, when my_errno will contain the error code.
+
+#.#.3 Errors
+
+HA_ERR_OLD_FILE
+wrong options
+HA_ERR_CRASHED
+wrong header
+HA_ERR_UNSUPPORTED
+too many keys or keys too long
+HA_ERR_END_OF_FILE
+empty file?
+MY_FILE_ERROR
+?
+EACCES
+cannot open in write mode
+ENOMEM
+not enough memory
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+pfm = mi_open("/D1/adir/perform",O_SHARE | O_RDONLY, HA_OPEN_ABORT_IF_LOCKED);
+====================
+#.# mi_panic()
+
+int mi_panic( enum ha_panic_function flag )
+
+#.#.1 Description
+
+mi_panic() is used to close any MyISAM files before exiting, or to safeguard file updates when using a shell.
+The flag parameter specifies the function and can be:
+HA_PANIC_CLOSE Close all databases (MyISAM files).
+HA_PANIC_WRITE Unlock and write status, flushing all buffers to disk.
+HA_PANIC_READ Lock and read key info per HA_PANIC_WRITE.
+
+The CLOSE function also writes buffers before it closes and turns logging off by closing the log file..
+See also my_end(), a debugging function.
+One use is to do a WRITE, use a shell to run myisamchk, then do a READ.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+result = mi_panic(HA_PANIC_CLOSE);
+====================
+#.# mi_position()
+
+my_off_t mi_position(MI_INFO *mip)
+
+#.#.1 Description
+
+Gets the byte position in the file of the last record read.
+
+mip is an MI_INFO pointer to the open handle.
+
+#.#.2 Return values
+
+Byte position if successful. Zero if an error occurred. ??
+
+#.#.3 Errors
+
+HA_OFFSET_ERROR
+if there wasn't any active row.
+
+#.#.4 Examples
+
+currentpos = mi_position( mip );
+====================
+#.# mi_rfirst()
+
+int mi_rfirst(MI_INFO *mip , byte *buf, int inx)
+
+#.#.1 Description
+
+Reads the first row in the MyISAM file according to the specified index.
+If one want's to read rows in physical sequences, then one should instead use mi_scan() or mi_rrnd().
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+Inx is the index (key) number, which must be the same as currently selected.
+
+mi_rfirst() works by setting the current position mip->lastpos to HA_OFFSET_ERROR (undefined) then calling mi_rnext().
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_END_OF_FILE
+End of file
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+error = mi_rfirst( mip, buffer, keynum);
+====================
+#.# mi_rkey()
+
+int mi_rkey(MI_INFO *mip, byte *buf, int inx, const byte *key, uint key_len, enum ha_rkey_function search_flag)
+
+#.#.1 Description
+
+Reads the next row after the last row read, using the current index.
+If one want's to read rows in physical sequences, then one should instead use mi_scan() or mi_rrnd().
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+Inx is the index (key) number, which must be the same as currently selected.
+
+If (mip->lastpos) is HA_OFFSET_ERROR (undefined) then mi_rnext() gives the first row.
+If you specify a different index number than the last read used, you will get an error.
+If the last (current) row has been changed since we read it, mi_rnext() will reposition from the position where that row WAS, not where it is now. (This behaviour is similar to CISAM and better than used in Codebase.)
+
+mi_extra(HA_EXTRA_KEYREAD) can be called first, to cause mi_rkey to read the key but not the record. Then call mi_extra(HA_EXTRA_NO_KEYREAD) to resume normal behaviour.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_END_OF_FILE
+End of file
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+error = mi_rnext( mip, buffer, keynum );
+====================
+#.# mi_rlast()
+
+int mi_rlast(MI_INFO *mip , byte *buf, int inx)
+
+#.#.1 Description
+
+Reads the last row in the MyISAM file according to the specified index.
+If one want's to read rows in physical sequences, then one should instead use mi_scan() or mi_rrnd().
+mip is an MI_INFO pointer to the open handle.
+buf is a pointer to the record buffer that will contain the row.
+Inx is the index (key) number, which must be the same as currently selected.
+
+mi_rlast() works by setting the current position (mip->lastpos) to HA_OFFSET_ERROR (undefined) then calling mi_rprev().
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_END_OF_FILE
+End of file
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+error = mi_rlast( mip, buffer, keynum);
+====================
+#.# mi_rnext()
+
+int mi_rnext(MI_INFO *mip , byte *buf, int inx )
+
+#.#.1 Description
+
+Reads the next row after the last row read, using the current index.
+If one want's to read rows in physical sequences, then one should instead use mi_scan() or mi_rrnd().
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+Inx is the index (key) number, which must be the same as currently selected.
+
+If (mip->lastpos) is HA_OFFSET_ERROR (undefined) then mi_rnext() gives the first row.
+If you specify a different index number than the last read used, you will get an error.
+If the last (current) row has been changed since we read it, mi_rnext() will reposition from the position where that row WAS, not where it is now. (This behaviour is similar to CISAM and better than used in Codebase.)
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_END_OF_FILE
+End of file
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+error = mi_rnext( mip, buffer, keynum );
+====================
+#.# mi_rrnd()
+
+int mi_rrnd( MI_INFO *mip , byte *buf, my_off_t filepos )
+
+#.#.1 Description
+
+Reads a row based on physical position.
+
+Position can be calculated from record number only when fixed record lengths are used:
+position = mip->s.pack.header_length + recnum * mip->s->base.reclength.
+If filepos= HA_OFFSET_ERROR then it reads the next row.
+And if (mip->lastpos == HA_OFFSET_ERROR) it reads the first row.
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+filepos is the byte position in the file of the required record.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_RECORD_DELETED
+A deleted record was read.
+HA_ERR_END_OF_FILE
+End of file.
+
+#.#.4 Examples
+
+error = mi_rrnd( mip, buffer, mip->nextpos );
+====================
+#.# mi_rprev()
+
+int mi_rprev(MI_INFO *mip , byte *buf, int inx)
+
+#.#.1 Description
+
+Reads the row previous to the last row read, using the current index.
+If one wants to read rows in physical sequences, then one should instead use mi_scan() or mi_rrnd().
+
+If (mip->lastpos) is HA_OFFSET_ERROR (undefined) then mi_rnext() gives the last row in the index.
+If you specify a different index number than the last read used, you will get an error.
+If the last (current) row has been changed since we read it, mi_rprev() will reposition from the position where that row WAS, not where it is now. This behaviour is similar to CISAM and better than used in Codebase.
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+Inx is the index (key) number, which must be the same as currently selected.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_END_OF_FILE
+End of file
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+error = mi_rprev( mip, buffer, keynum );
+====================
+#.# mi_rsame()
+
+int mi_rsame(MI_INFO *mip, byte *buf, int inx)
+
+#.#.1 Description
+
+Reads the current row to get its latest contents. This is useful to refresh the record buffer in case someone else has changed it.
+If inx is negative it reads by position. If inx is >= 0 it reads by key.
+With mi_rsame() one can switch to use any other index for the current row. This is good if you have a user application that lets the user do 'read-next' on a row. In this case, if the user want's to start scanning on another index, one simply has to do a mi_rsame() on the new index to activate this.
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+inx is the index (key) number, or a negative number to select read by position not index. Maybe the negative number has to be (-1) to achieve this behaviour.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_WRONG_INDEX
+an incorrect index number was supplied
+HA_ERR_KEY_NOT_FOUND
+info->lastpos was not defined, or the record was already deleted.
+
+#.#.4 Examples
+
+error = mi_rsame( m5mip, rec_ptr, keynum );
+====================
+#.# mi_scan()
+
+int mi_scan(MI_INFO *mip, byte *buf)
+
+#.#.1 Description
+
+Reads the next row by physical position.
+
+Deleted rows are bypassed.
+mi_scan() uses a function pointer "read_rnd" that uses either lower level static or dynamic read functions, positioning from mip->nextpos. Read_rnd is defined in mi_open() depending if the table is Static (read*static - see mi_statrec.c), Compressed (read*pack - see mi_packrec.c), or Space packed or Blobs (read*dynamic - see mi_dynrec.c).
+See also mi_scan_init() which initialises ready to mi_scan() through the whole table.
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_END_OF_FILE
+End of file
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+error = mi_scan( mip, recbuff );
+====================
+#.# mi_scan_init()
+
+int mi_scan_init(MI_INFO *mip[SB1])
+
+#.#.1 Description
+
+Initialises ready to mi_scan() through all rows.
+
+mip is an MI_INFO pointer to the open handle.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+====================
+#.# mi_status()
+
+int mi_status(MI_INFO *mip, MI_ISAMINFO *x, uint flag)
+
+#.#.1 Description
+
+Gets information about the table.
+It is used to get/fill the MI_ISAMINFO struct with statistics data about the MySQL server. One can get information of the number of active rows, delete rows, file lengths...
+
+mip is an MI_INFO pointer to the open handle.
+flag is one of the following:
+HA_STATUS_POS Return position
+HA_STATUS_NO_LOCK Don't use external lock
+HA_STATUS_TIME Return update time
+HA_STATUS_CONST Return constants value
+HA_STATUS_VARIABLE
+HA_STATUS_ERRKEY
+HA_STATUS_AUTO
+
+#.#.2 Return values
+
+Zero.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+====================
+#.# mi_update()
+
+int mi_update( MI_INFO *mip, const byte *oldbuf, byte *newbuf)
+
+#.#.1 Description
+
+Updates the contents of the current record.
+By default you must supply an oldbuf record buffer with the current record contents. This is compared with the file as a guard in case someone else has changed the record in the meantime. *
+
+mip is an MI_INFO pointer to the open handle.
+oldbuf is the record buffer that contains the current record contents.
+newbuf is the record buffer that contains the new record contents.
+
+*Sometimes you might want to force an update without checking whether another user has changed the record since you last read it. This is somewhat dangerous, so it should ideally not be used. That can be accomplished by wrapping the mi_update() call in two calls to mi_extra(), using these functions:
+HA_EXTRA_NO_READCHECK=5 No readcheck on update
+HA_EXTRA_READCHECK=6 Use readcheck (def)
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+EACCES
+The file was opened for read-only access.
+HA_ERR_RECORD_CHANGED
+ When mi_update() read the current record contents before updating, it differed from oldbuf.
+HA_ERR_CRASHED
+Key could not be found ??
+HA_ERR_FOUND_DUPP_KEY
+HA_ERR_RECORD_FILE_FULL
+
+#.#.4 Examples
+
+error = mi_update( mip, oldbuf, newbuf );
+====================
+#.# mi_write()
+
+int mi_write( MI_INFO *mip, byte *record)
+
+#.#.1 Description
+
+Writes a row to a MyISAM table.
+
+mip is an MI_INFO pointer to the open handle.
+The record contents are supplied in buf record buffer.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_FOUND_DUPP_KEY
+A record already existed with a unique key same as this new record.
+HA_ERR_RECORD_FILE_FULL
+The error is given if you hit a system limit or if you try to create more rows in a table that you reserverd room for with mi_create().
+ENOSPC
+The disk is full.
+EACCES
+The file was opened for read-only access.
+
+#.#.4 Examples
+
+error = mi_write( m5mip, recbuf );
+====================
+#.# my_end()
+
+void my_end(int infoflag)
+
+#.#.1 Description
+
+Shows debugging information about open MyISAM handles.
+my_end() exists primarily for MyISAM debugging.
+It would not normally be used in a production environment.
+It can give a nice summary of how you have used my_xxx() functions.
+It can be used to check that you have closed all files that you have opened.
+
+infoflag is the list function and can be:
+MY_CHECK_ERROR List which MyISAM handles are open.
+MY_GIVE_INFO Show runtime information.
+
+#.#.2 Return values
+
+Void
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+my_end(MY_CHECK_ERROR | MY_GIVE_INFO);
+====================
+#.# my_init()
+
+void my_init( void )
+
+#.#.1 Description
+
+Performs MyISAM initialisation for program startup, particularly if using threads.
+
+If using threads, be sure to call my_init() at start of program. (CFS does this in XPOPEN.) It is also safe to call my_init() when not using threads.
+
+#.#.2 Return values
+
+void
+Sometimes my_errno might be meaningful if a warning is generated during debugging.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+my_init();
+====================
+#.# init_key_cache()
+
+int init_key_cache( long int use_mem, (uint) reserve_mem;
+
+#.#.1 Description
+
+Starts and controls caching of keys. Call init_key_cache() to reserve memory for key caching and to start the caching. (CFS does this in XPOPEN if MYCACHE is defined (regular size), or MYCACHELARGE or MYCACHESMALL.)
+
+Provide use_mem the number of bytes of memory to use for key caching by this process.
+reserve_mem should be 0. This is just for very old systems with very little memory.
+
+#.#.2 Return values
+
+The number of 1kb memory blocks now allocated to key caching. Zero if key caching cannot be started (check my_errno), or key caching was already active.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+Blocks = init_key_cache( 65536L, IO_SIZE*4*10 );
+====================
+#.# _mi_make_key()
+
+uint _mi_make_key( MI_INFO *mip, uint keynr, uchar *key, const char *record, my_off_t filepos)
+
+#.#.1 Description
+
+Construct a key string for the given index, from the provided record buffer.
+??? When packed records are used ...
+This is an internal function, not for use by applications. Monty says: "This can't be used to create an external key for an application from your record."
+See mi_make_application_key() for a similar function that is useable by applications.
+
+The parameters are:
+A MI_INFO pointer mip.
+The index number keynr.
+The buffer to contain the formatted key string key.
+The record buffer record.
+??? A file position filepos or zero.
+
+#.#.2 Return values
+
+The byte length of the created key string.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+uint new_length=_mi_make_key(info,i,new_key,newrec,pos);
+====================
+#.# _mi_print_key()
+
+void _mi_print_key(FILE *stream, MI_KEYSEG *keyseg, const uchar *key, uint length)
+
+#.#.1 Description
+
+Prints a key in a user understandable format.
+This is an internal function for debugging, not for use by applications.
+??? Not yet fully documented. I just include it here so that I know it exists.
+
+#.#.2 Return values
+
+A readable print of the key contents goes to the specified output.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+_mi_print_key(stdout,share->keyinfo[info->errkey].seg,info->lastkey, USE_WHOLE_KEY);
+====================
+APPENDIX B Choosing a table type
+(excerpt from manual.txt in MySQL 3.23.8-alpha)
+
+With MySQL you can currently (version 3.23.5) choose between four usable table formats from a speed point of view.
+
+Static (Fixed-length) table characteristics
+* This is the default format. It's used when the table contains no `VARCHAR', `BLOB' or `TEXT' columns.
+* All `CHAR', `NUMERIC' and `DECIMAL' columns are space-padded to the column width.
+* Very quick.
+* Easy to cache.
+* Easy to reconstruct after a crash, because records are located in fixed positions.
+* Doesn't have to be reorganized (with `myisamchk') unless a huge number of records are deleted and you want to return free disk space to the operating system.
+* Usually requires more disk space than dynamic tables.
+
+Dynamic table characteristics
+* This format is used if the table contains any `VARCHAR', `BLOB' or `TEXT' columns.
+* All string columns are dynamic (except those with a length less than 4).
+* Each record is preceded by a bitmap indicating which columns are empty (`''') for string columns, or zero for numeric columns (this isn't the same as columns containing `NULL' values). If a string column has a length of zero after removal of trailing spaces, or a numeric column has a value of zero, it is marked in the bit map and not saved to disk. Non-empty strings are saved as a length byte plus the string contents.
+* Usually takes much less disk space than fixed-length tables.
+* Each record uses only as much space as is required. If a record becomes larger, it is split into as many pieces as required. This results in record fragmentation.
+* If you update a row with information that extends the row length, the row will be fragmented. In this case, you may have to run `myisamchk -r' from time to time to get better performance. Use `myisamchk -ei tbl_name' for some statistics.
+* Not as easy to reconstruct after a crash, because a record may be fragmented into many pieces and a link (fragment) 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 numeric columns
++ length of strings
++ (number of NULL columns + 7) / 8
+There is a penalty of 6 bytes for each link. A dynamic record is linked whenever an update causes an 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 `myisamchk -ed'. All links may be removed with `myisamchk -r'.
+
+Compressed table characteristics
+* A read-only table made with the `myisampack' utility. All customers with extended *MySQL* email support are entitled to a copy of `myisampack' for their internal usage.
+* The uncompress code exists in all *MySQL* distributions so that even customers who don't have `myisampack' can read tables that were compressed with `myisampack'
+* Takes very little disk space. Minimises disk usage.
+* Each record is compressed separately (very little access overhead). The header for a record is fixed (1-3 bytes) depending on the biggest record in the table. Each column is compressed differently. Some of the compression types are:
+- There is usually a different Huffman table for each column.
+- Suffix space compression.
+- Prefix space compression.
+- Numbers with value `0' are stored using 1 bit.
+- If values in an integer column have a small range, the column is stored using the smallest possible type. For example, a `BIGINT' column (8 bytes) may be stored as a `TINYINT' column (1 byte) if all values are in the range `0' to `255'.
+- If a column has only a small set of possible values, the column type is converted to `ENUM'.
+- A column may use a combination of the above compressions.
+* Can handle fixed or dynamic length records, but not `BLOB' or `TEXT' columns.
+* Can be uncompressed with `myisamchk'.
+
+*MySQL* can support different index types, but the normal type is ISAM.
+This is a B-tree index and you can roughly calculate the size for the index file as `(key_length+4)*0.67', summed over all keys. (This is for the worst case when all keys are inserted in sorted order.)
+
+String indexes are space compressed. If the first index part is a string, it will also be prefix compressed.
+Space compression makes the index file smaller if the string column has a lot of trailing space or is a `VARCHAR' column that is not always used to the full length.
+Prefix compression helps if there are many strings with an identical prefix.
+
+In memory table characteristics
+HEAP tables only exists in memory so they are lost if `mysqld' is taken down or crashes. But since they are *very* fast they are usefull as anyway.
+
+The *MySQL* internal HEAP tables uses 100% dynamic hashing without overflow areas and don't have problems with delete.
+
+You can only access things by equality using a index (usually by the `=' operator) whith a heap table.
+The downside with HEAPS are:
+ 1. You need enough extra memory for all HEAP tables that you want to use at the same time.
+ 2. You can't search on a part of a index.
+ 3. You can't search for the next entry in order (that is to use the index to do a `ORDER BY').
+1. *MySQL* also cannot find out how approximately many rows there are between two values. This is used by the optimizer to chose which index to use. But on the other hand no disk seeks are even needed.
+====================
+#.# mi_()
+
+#.#.1 Description
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+[SB1]int _mi_read_rnd_static_record(MI_INFO *info, byte *buf, my_off_t filepos,
+ my_bool skipp_deleted_blocks)
+int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf)
+
+Printed on 17/03/00
+
+C-7
diff --git a/Docs/Flags/australia.eps b/Docs/Flags/australia.eps
new file mode 100755
index 00000000000..f98c03e2c83
--- /dev/null
+++ b/Docs/Flags/australia.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+cf7b0e0808087cc6730808081084c4080808080808080808080808080808
+3f5c0600000050005300000009603a000000000000000000000000000000
+43b5b6b5b5b5a600b1b5b5b5b7b246b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+b1d2b73608087cc67308083dbcd3a5080808080808080809080808080808
+8d3e612f00005000530000355e4285000000000000000001000000000000
+bc3e82c0b5b5a600b1b5b5c17a43bfb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+096bd4cf7b0e7cc6731083d0d36108080808080808084d990c0808080808
+0162753f5c06500053095f3c7b5b00000000000000004796040000000000
+b5cd7e43b5b7a600b1b7b13e87ccb5b5b5b5b5b5b5b5c8ddb6b5b5b5b5b5
+0c0c2bb5d3b8a3c6a2bcd3ae250c0c080808080808087bba170808080808
+040424913e6478008061438f1e04040000000000000077b70f0000000000
+b6b6bfbd3f85b000bc7d43c1bdb6b6b5b5b5b5b5b5b5d5e6b9b5b5b5b5b5
+d5d5d5d5d5d5d2c6d3d5d5d5d5d5c9080808080808080d0d080808080808
+4c4c4c4c4c4a3c00414a4c4c4c4c48000000000000000505000000000000
+4c4c4c4c4c4a3c00414a4c4c4c4c52b5b5b5b5b5b5b5b6b6b5b5b5b5b5b5
+d3d3d3d4d7d6d4c6d4d6d7d4d3d3c7080808080808080808080808080808
+51515152545044004950555251514c000000000000000000000000000000
+55555555545044004950555555555bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0a0a2fb9d2b19fc69db7d2b3290a0a080808080808080808080808080808
+0202288f3a6374007c613e8e220202000000000000000000000000000000
+b5b5c0b73b8aaf00bb823ebcbeb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0b74d6ce720b7cc6730e7bcfd46b0908080808080808080808080c080808
+036b6f435703500053065c3f756201000000000000000000000004000000
+b6cd7649b8b6a600b1b7b5437ecdb5b5b5b5b5b5b5b5b5b5b5b5b6b5b5b5
+b9d2b12f08087cc673080836b7d2ab080808110808080808080eac520808
+8f3a6328000050005300002f613e870000000a00000000000006a94d0000
+b73a8abfb5b5a600b1b5b5c0823ebab5b5b5b8b5b5b5b5b5b5b6e2cab5b5
+c7720b08080877bf6f0808080e7abd080819c757080808080819ae6f0808
+3c57030000004d004f000000065b37000011c552000000000012ac6a0000
+47b8b6b5b5b5a607b1b5b5b5b7b54ab5b5baeacbb5b5b5b5b5bae3d1b5b5
+08080808080808080808080808080808081c9e50080808080f080a0a0808
+0000000000000000000000000000000000149a4a00000000070002020000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5badec9b5b5b5b5b7b5b6b5b5b5
+0808080808080808080808080808080808080808080808119a0b08080808
+000000000000000000000000000000000000000000000009960300000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b7ddb6b5b5b5b5
+0808080808080808080808080808080808080808080808080c0808080808
+000000000000000000000000000000000000000000000000040000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b6b5b5b5b5b5
+080808080808080c08080808080808080808080808080808080808080808
+000000000000000400000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080809439144090808080808080808080808080808080808080808
+0000000000013d8e3d010000000000000000000000000000000000000000
+b5b5b5b5b5b5c5dbc5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080809b0f7b1090808080808080808080808081308080808080808
+000000000001adf7af010000000000000000000000000c00000000000000
+b5b5b5b5b5b5e3f7e4b5b5b5b5b5b5b5b5b5b5b5b5b5b8b5b5b5b5b5b5b5
+08080808081c8eed8f1d08080808080808080808083ccc3a080808080808
+0000000000158aed8c15000000000000000000000035cb34000000000000
+b5b5b5b5b5bbdaf4dabbb5b5b5b5b5b5b5b5b5b5b5c3ebc3b5b5b5b5b5b5
+0808080808082c1b2c08080808080808080808080827af26080808080808
+0000000000002513250000000000000000000000001fac1e000000000000
+b5b5b5b5b5b5bfbabfb5b5b5b5b5b5b5b5b5b5b5b5bde3bdb5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/australia.gif b/Docs/Flags/australia.gif
new file mode 100644
index 00000000000..1f403f92503
--- /dev/null
+++ b/Docs/Flags/australia.gif
Binary files differ
diff --git a/Docs/Flags/australia.txt b/Docs/Flags/australia.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/australia.txt
diff --git a/Docs/Flags/austria.eps b/Docs/Flags/austria.eps
new file mode 100755
index 00000000000..7a0b56f3690
--- /dev/null
+++ b/Docs/Flags/austria.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7
+575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4
+464646464646464646464646464646464646464646464646464646464646
+474747474747474747474747474747474747474747474747474747474747
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/austria.gif b/Docs/Flags/austria.gif
new file mode 100644
index 00000000000..d72b945741a
--- /dev/null
+++ b/Docs/Flags/austria.gif
Binary files differ
diff --git a/Docs/Flags/austria.txt b/Docs/Flags/austria.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/austria.txt
diff --git a/Docs/Flags/brazil.eps b/Docs/Flags/brazil.eps
new file mode 100644
index 00000000000..94cbbd42d20
--- /dev/null
+++ b/Docs/Flags/brazil.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000001eb8a41300000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5beebe5bab5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000164f1ffffe74f000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5d2fbfffff8ccb5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000001eb8fffffcfdffffa41300000000000000000000
+b5b5b5b5b5b5b5b5b5b5beebfffffefeffffe5bab5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000003020000000000000000000000000000
+00000000000000000163f0fea8451c1e4eb8ffe750000000000000000000
+b5b5b5b5b5b5b5b5b5d2fbffe3c3b6b7c6e8fff8ccb5b5b5b5b5b5b5b5b5
+0000000000000000000000015ac1ebe9b84a000000000000000000000000
+000000000000001db7fffe6f18181818181889ffffa41300000000000000
+b5b5b5b5b5b5b5beeaffffd1b5b5b5b5b5b5d9ffffe5bab5b5b5b5b5b5b5
+000000000000000000000195efefefefefef7a0000000000000000000000
+00000000000163f0ffffa61818181818181818c1ffffe750000000000000
+b5b5b5b5b5b5d2fbffffe2b5b5b5b5b5b5b5b5ebfffff8ccb5b5b5b5b5b5
+000000000000000000005cefefefefefefefef4100000000000000000000
+000000001db7ffffffffd4b5bea7905c2b18185dffffffffa41300000000
+b5b5b5b5beeaffffffffeee4e6e0d9c9bbb5b5cbffffffffe5bbb5b5b5b5
+00000000000000000000c9f5f5f4f3f2f0efefa800000000000000000000
+00000063f0fffffffffa422122395f8aae661d30ffffffffffe74f000000
+b5b5b5d2fbfffffffffdc2b8b8bfcad7e2cdb7bdfffffffffff8ccb5b5b5
+00000000000000000006eff0f0f0f2f3f4f2efd700000000000000000000
+00000050e7fffffffffa1b1e181b1b1836909948ffffffffffdb3d000000
+b5b5b5ccf8fffffffffeb6b7b5b6b6b5bed9dcc4fffffffffff5c7b5b5b5
+00000000000000000005ecefefefefeff0f4f4d600000000000000000000
+0000000013a5ffffffff481c18181f1818196fdefffffffd900a00000000
+b5b5b5b5bbe5ffffffffc4b6b5b5b7b5b5b5cff2fffffffedfb8b5b5b5b5
+00000000000000000000beefefefefefefeff2a600000000000000000000
+00000000000050e7ffffb01823182218282e39d9ffffdb3d000000000000
+b5b5b5b5b5b5ccf8ffffe6b5b8b5b8b5babcbff3fffff5c7b5b5b5b5b5b5
+0000000000000000000051efefefefeff0f0ee3800000000000000000000
+0000000000000013a5ffff8018181b18283a99fffd900a00000000000000
+b5b5b5b5b5b5b5bbe5ffffd7b5b5b6b5babfdffffedfb8b5b5b5b5b5b5b5
+000000000000000000000084efefefeff0ef690000000000000000000000
+00000000000000000050e7ffba572b2d60c8ffdb3d000000000000000000
+b5b5b5b5b5b5b5b5b5ccf8ffe9c9bbbcccedfff5c7b5b5b5b5b5b5b5b5b5
+00000000000000000000000048aedcd9a539000000000000000000000000
+0000000000000000000013a5fffffffffffd900a00000000000000000000
+b5b5b5b5b5b5b5b5b5b5bbe5fffffffffffedfb8b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000050e7ffffdb3e000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5ccf8fffff5c7b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000013a5910b00000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5bbe5dfb8b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/brazil.gif b/Docs/Flags/brazil.gif
new file mode 100644
index 00000000000..82e12be5956
--- /dev/null
+++ b/Docs/Flags/brazil.gif
Binary files differ
diff --git a/Docs/Flags/brazil.txt b/Docs/Flags/brazil.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/brazil.txt
diff --git a/Docs/Flags/bulgaria.eps b/Docs/Flags/bulgaria.eps
new file mode 100644
index 00000000000..6f4a07c616c
--- /dev/null
+++ b/Docs/Flags/bulgaria.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8d
+333333333333333333333333333333333333333333333333333333333333
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/bulgaria.gif b/Docs/Flags/bulgaria.gif
new file mode 100644
index 00000000000..35c0b117062
--- /dev/null
+++ b/Docs/Flags/bulgaria.gif
Binary files differ
diff --git a/Docs/Flags/bulgaria.txt b/Docs/Flags/bulgaria.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/bulgaria.txt
diff --git a/Docs/Flags/canada.eps b/Docs/Flags/canada.eps
new file mode 100755
index 00000000000..b770266de60
--- /dev/null
+++ b/Docs/Flags/canada.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+c6c6c6c6c6c6c6e0f7f7f7f7f7f7f7f7f7f7f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7f7f7f7f7f7f7f7f7f7f76300000000000000
+0000000000000083f7f7f7f7f7f7f7f7f7f7f7f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f7f7f7f7f7f7f7f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7f7f7f7f7f7f7f7f7f7f76300000000000000
+0000000000000083f7f7f7f7f7f7f7f7f7f7f7f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f7f7f7f7f7f7f7f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7f7f7f7f7f7f7f7f7f7f76300000000000000
+0000000000000083f7f7f7f7f7f7f7f7f7f7f7f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f7f7f7f6f7f7f7f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7f7f7f3f7f7f7f7f7f7f76300000000000000
+0000000000000083f7f7f7f7f7f7f3f7f7f7f7f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f7f7f7e5ebf7f7f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7f7f79dbaf7f7f7f7f7f76300000000000000
+0000000000000083f7f7f7f7f7f79dbaf7f7f7f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f7f6f5d0d6f4f7f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7f2ed324fe9f7f7f7f7f76300000000000000
+0000000000000083f7f7f7f7f2ed324fe9f7f7f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f7f7d2c6c7d7f7f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7f73c000355f7f7f7f7f76300000000000000
+0000000000000083f7f7f7f7f73c000356f7f7f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f1f7dac6c6e0f7f1f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7d7f764000081f6d9f7f7f76300000000000000
+0000000000000083f7f7f7d8f764000081f6d9f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7ede8d6d5e1c6c6e5d1dbe6f0f7dac6c6c6c6c6c6c6
+0000000000000083f7c4a951488a00009a3869a0d2f76300000000000000
+0000000000000083f7c4a952488a00009a386aa0d2f76300000000000000
+c6c6c6c6c6c6c6e0f7f3c7c6c6c7c6c6c7c6c6caf6f7dac6c6c6c6c6c6c6
+0000000000000083f7e106000003000002000014f0f76300000000000000
+0000000000000083f7e106000003000002000014f0f76300000000000000
+c6c6c6c6c6c6c6e0f7efcbc6c6c6c6c6c6c6c6cff1f7dac6c6c6c6c6c6c6
+0000000000000083f7cd1b00000000000000002bd9f76300000000000000
+0000000000000083f7cd1b00000000000000002bd9f76300000000000000
+c6c6c6c6c6c6c6e0f7f7eeddccc6c6c6c6cedff0f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7c87420000000002a7ed2f7f76300000000000000
+0000000000000083f7f7c87420000000002a7ed2f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f7d7c6c7c7c6ddf7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7560003030072f7f7f7f76300000000000000
+0000000000000083f7f7f7f7560003030073f7f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f6f0f5e7edf4f0f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f2d6eaa8c4e8d4f6f7f7f76300000000000000
+0000000000000083f7f7f7f2d6eaa8c5e8d5f6f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f7f7f7e6ecf7f7f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7f7f7a3c0f7f7f7f7f7f76300000000000000
+0000000000000083f7f7f7f7f7f7a4c1f7f7f7f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f7f7f7e6ebf7f7f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7f7f79fbcf7f7f7f7f7f76300000000000000
+0000000000000083f7f7f7f7f7f79fbcf7f7f7f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f7f7f7f5f6f7f7f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7f7f7edf0f7f7f7f7f7f76300000000000000
+0000000000000083f7f7f7f7f7f7edf0f7f7f7f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f7f7f7f7f7f7f7f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7f7f7f7f7f7f7f7f7f7f76300000000000000
+0000000000000083f7f7f7f7f7f7f7f7f7f7f7f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f7f7f7f7f7f7f7f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7f7f7f7f7f7f7f7f7f7f76300000000000000
+0000000000000083f7f7f7f7f7f7f7f7f7f7f7f7f7f76300000000000000
+c6c6c6c6c6c6c6e0f7f7f7f7f7f7f7f7f7f7f7f7f7f7dac6c6c6c6c6c6c6
+0000000000000083f7f7f7f7f7f7f7f7f7f7f7f7f7f76300000000000000
+0000000000000083f7f7f7f7f7f7f7f7f7f7f7f7f7f76300000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/canada.gif b/Docs/Flags/canada.gif
new file mode 100644
index 00000000000..322d4b985b7
--- /dev/null
+++ b/Docs/Flags/canada.gif
Binary files differ
diff --git a/Docs/Flags/canada.txt b/Docs/Flags/canada.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/canada.txt
diff --git a/Docs/Flags/chile.eps b/Docs/Flags/chile.eps
new file mode 100644
index 00000000000..8a5411a32a3
--- /dev/null
+++ b/Docs/Flags/chile.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+08080808080808080811f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+0000000000000000000af7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+08080808272008080811f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+0000000020190000000af7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5b5bebcb5b5b5b8f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+08080808776e08080811f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+0000000073690000000af7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5b5d4d1b5b5b5b8f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+08080808c7bd08080811f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+00000000c5bb0000000af7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5b5eae7b5b5b5b8f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+0868e3e9f7f6e9e16111f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+0062e2e8f7f6e8e05b0af7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5cff1f3f7f7f3f1cdb8f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+08083eddf7f7d9390811f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+000038dcf7f7d833000af7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5c4f0f7f7efc3b5b8f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+080808c1f7f7b8080811f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+000000bff7f7b500000af7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5e8f7f7e5b5b5b8f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+08081fe86066e8190811f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+000018e85b61e711000af7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5bbf3cdcff3bab5b8f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+08083a2808082c360811f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+000033210000262f000af7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5c3beb5b5bfc2b5b8f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+0e0e0e0e0e0e0e0e0e17f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+00000000000000000009f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0
+b0b0b0b0b0b0b0b0b0b3f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000101010101010101010101010101010101010101
+010101010101010101010101010101010101010101010101010101010101
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/chile.gif b/Docs/Flags/chile.gif
new file mode 100644
index 00000000000..e7afe88df8b
--- /dev/null
+++ b/Docs/Flags/chile.gif
Binary files differ
diff --git a/Docs/Flags/chile.txt b/Docs/Flags/chile.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/chile.txt
diff --git a/Docs/Flags/china.eps b/Docs/Flags/china.eps
new file mode 100644
index 00000000000..97b87f4727f
--- /dev/null
+++ b/Docs/Flags/china.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c7e1c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000037602000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6cfc6c6c6c9c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000250000000e00000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6efc9c6c6c7e1c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000b70e00000377010000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6d7f4fef7e2c7c6c9c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+004bccfcda7d03000d000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6e2fff2c6c6c7d3c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+00007dffc301000338010000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6e5d4e9c8c6c6d7c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+00008a3b9c0a00004c000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c7c6c6c7c7d0c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000003000003042a00000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6dac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000015800000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/china.gif b/Docs/Flags/china.gif
new file mode 100644
index 00000000000..4baf243f158
--- /dev/null
+++ b/Docs/Flags/china.gif
Binary files differ
diff --git a/Docs/Flags/china.txt b/Docs/Flags/china.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/china.txt
diff --git a/Docs/Flags/croatia.eps b/Docs/Flags/croatia.eps
new file mode 100644
index 00000000000..db6566f8e31
--- /dev/null
+++ b/Docs/Flags/croatia.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6b6c1abafc0b8c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000170d2f290f15000000000000000000000000
+0000000000000000000000001e0e312a111b000000000000000000000000
+c6c6c6c6c6c6c6c6c6c67a77748c474c29297380c6c6c6c6c6c6c6c6c6c6
+0000000000000000000076703536b1ac3d3c756e00000000000000000000
+0000000000000000000074715b4b908a838c756d00000000000000000000
+c6c6c6c6c6c6c6c6c6c22c1858652b257a5b6947c4c6c6c6c6c6c6c6c6c6
+00000000000000000013c5c93529b6ae755ca6c30c000000000000000000
+00000000000000000013bcc86157a5a5435a9bbb0c000000000000000000
+c6c6c6c6c6c6c6c6c6c65e3c4f60605f5d5466acc6c6c6c6c6c6c6c6c6c6
+0000000000000000000095d065397d794264674300000000000000000000
+000000000000000000009cdb876a878669856b4400000000000000000000
+d7d7d7d7d7d7d7d7d7d7bcb3cfd8c8cad8cdb1c1d7d7d7d7d7d7d7d7d7d7
+57575757575757575757592a345a0b155a292d6057575757575757575757
+575757575757575757575b2b345a0b155a292f6157575757575757575757
+f7f7f7f7f7f7f7f7f7f7e2c6e2f7ccd2f7dbc6e8f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f78d008af71e3af76b00adf7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f78d008bf71e3af76b00adf7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7eae9ded5e7e5d5e1e9ecf7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7b3af794ba5994b86afbff7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7b3af7a4ca59a4c87afbff7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7edf6ddc8f1ecc8e3f6edf7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7c1f0720ad7bc0a8ff0c5f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7c1f0720ad8bd0a90f0c5f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7e2c6e2f7ccd2f7dbc6e8f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f78e018bf71e3bf76b01adf7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f78e018bf71e3bf76b01adf7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7e7d9e0e5dbdce5ded8ecf7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7a75e819b666e9b795bbcf7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7a75f829b676e9b7a5cbcf7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f3f0dcc6f2ecc6e3edf6f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7e1d56f00dcbf008fc6f0f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7e1d56f00ddc00090c6f0f7f7f7f7f7f7f7f7f7f7
+4c4c4c4c4c4c4c4c4c4c4c79e1ead7d9eadd6a4c4c4c4c4c4c4c4c4c4c4c
+46464646464646464646463484b45461b476344646464646464646464646
+c8c8c8c8c8c8c8c8c8c8c88885b45562b47897c8c8c8c8c8c8c8c8c8c8c8
+0808080808080808080808085cd3cbd0ca4a080808080808080808080808
+0000000000000000000000002aa819319d1d000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b597bb1931b799b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080808080808080809201d0808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b49ea1b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/croatia.gif b/Docs/Flags/croatia.gif
new file mode 100644
index 00000000000..643b89555f5
--- /dev/null
+++ b/Docs/Flags/croatia.gif
Binary files differ
diff --git a/Docs/Flags/croatia.txt b/Docs/Flags/croatia.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/croatia.txt
diff --git a/Docs/Flags/czech-republic.eps b/Docs/Flags/czech-republic.eps
new file mode 100755
index 00000000000..afa50e9a82d
--- /dev/null
+++ b/Docs/Flags/czech-republic.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+56e2f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+50e1f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+caf1f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+081ba5f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+0014a2f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5bae0f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+08080856e2f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+00000050e1f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5caf1f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+080808081ba5f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+0000000014a2f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5b5bae0f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+08080808080856e2f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+00000000000050e1f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5b5b5b5caf1f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+080808080808081ba5f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+0000000000000014a2f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5b5b5b5b5bae0f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+08080808080808080856e2f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+00000000000000000050e1f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5b5b5b5b5b5b5cbf1f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+080808080808080808081ba5f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+0000000000000000000014a3f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5b5b5b5b5b5b5b5bae0f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+08080808080808080808080856e2f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+00000000000000000000000050e1f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5b5b5b5b5b5b5b5b5b5caf1f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+080808080808080808080808081ba6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+0000000000000000000000000014a3f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0
+b5b5b5b5b5b5b5b5b5b5b5b5b5bae0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0
+080808080808080808080808081f93c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000010101010101010101010101010101
+b5b5b5b5b5b5b5b5b5b5b5b5b59f31010101010101010101010101010101
+08080808080808080808080954bcc6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b46d0a00000000000000000000000000000000
+080808080808080808081f93c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b59f31000000000000000000000000000000000000
+08080808080808080954bcc6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b46d0a00000000000000000000000000000000000000
+080808080808081f92c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b59f31000000000000000000000000000000000000000000
+08080808080954bcc6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b46d0a00000000000000000000000000000000000000000000
+080808081f93c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b59f31000000000000000000000000000000000000000000000000
+08080954bcc6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+b5b5b46d0a00000000000000000000000000000000000000000000000000
+081f92c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+b59f31000000000000000000000000000000000000000000000000000000
+53bcc6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+6e0a00000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/czech-republic.gif b/Docs/Flags/czech-republic.gif
new file mode 100644
index 00000000000..10d5a3c72e9
--- /dev/null
+++ b/Docs/Flags/czech-republic.gif
Binary files differ
diff --git a/Docs/Flags/czech-republic.txt b/Docs/Flags/czech-republic.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/czech-republic.txt
diff --git a/Docs/Flags/denmark.eps b/Docs/Flags/denmark.eps
new file mode 100644
index 00000000000..2f397c4af16
--- /dev/null
+++ b/Docs/Flags/denmark.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+c7c7c7c7c7c7c7c9fffffffac7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c7c7c7c7c7c7c7c9fffffffac7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c7c6c7c6c6c6c7c9fffffffac7c6c6c6c6c6c6c6c6c6c6c6c6c6c7c6c7c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c7c7c7c6c7c7c7c9fffffff9c7c7c7c6c6c6c6c6c6c6c6c6c6c7c7c7c7c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c7c6c7c7c7c7c7c9fffffffac7c7c7c7c7c7c7c7c7c7c7c6c7c7c6c7c7c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c7c7c6c7c7c7c7c8fffffffac7c7c7c7c6c6c6c6c6c6c7c7c6c7c6c7c7c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c7c7c7c7c7c7c7c9fffffff9c7c7c7c7c6c6c6c6c6c6c7c7c7c7c7c7c7c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c7c7c7c7c7c7c6c9fffffffac6c7c7c7c7c6c6c6c7c7c7c7c7c7c6c7c7c8
+060606060606060efffffff0060606060606060606060606060606060606
+020202020202020affffffe9020202020202020202020202020202020202
+fefefefefefefefefffffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefffffffffefefefefefefefefefefefefefefefefefe
+fbfbfbfbfbfbfbfbfffffffffbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfbfb
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fdfdfdfdfdfdfdfdfffffffffdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfd
+f3f3f3f3f3f3f3f3fffffffef3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3
+f3f3f3f3f3f3f3f3fffffffef3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3
+c7c7c6c6c6c6c6c8fffffff9c7c6c6c6c7c6c6c6c6c6c7c6c6c6c6c6c6c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c7c6c6c7c7c7c7c8fffffff9c7c7c7c7c7c7c7c7c7c7c6c6c6c6c7c6c7c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c7c7c7c7c7c7c7c8fffffffac7c7c7c7c7c7c7c7c7c7c6c7c7c7c7c7c7c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c7c7c7c7c7c7c6c8fffffffac7c7c7c7c7c7c6c7c6c7c7c6c7c7c7c7c7c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c6c7c7c7c7c7c7c8fffffff9c7c7c7c7c7c7c7c6c7c7c7c7c7c7c6c7c7c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c7c7c7c7c6c7c7c9fffffff9c7c6c7c7c6c7c7c7c7c7c7c6c7c7c7c6c7c7
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c7c7c7c7c7c6c6c8fffffffac6c7c7c7c7c6c7c7c6c7c7c6c7c7c7c7c7c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+c7c7c7c7c7c7c6c9fffffffac6c7c6c7c6c6c6c7c7c7c7c7c6c7c6c7c7c8
+0000000000000008fffffff0000000000000000000000000000000000000
+0000000000000008ffffffe9000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/denmark.gif b/Docs/Flags/denmark.gif
new file mode 100644
index 00000000000..1d8e687adcc
--- /dev/null
+++ b/Docs/Flags/denmark.gif
Binary files differ
diff --git a/Docs/Flags/denmark.txt b/Docs/Flags/denmark.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/denmark.txt
diff --git a/Docs/Flags/estonia.eps b/Docs/Flags/estonia.eps
new file mode 100644
index 00000000000..e34768c3442
--- /dev/null
+++ b/Docs/Flags/estonia.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+050505050505050505050505050505050505050505050505050505050505
+000000000000000000000000000000000000000000000000000000000000
+757575757575757575757575757575757575757575757575757575757575
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1
+b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1
+b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/estonia.gif b/Docs/Flags/estonia.gif
new file mode 100644
index 00000000000..b8bbf1dbb78
--- /dev/null
+++ b/Docs/Flags/estonia.gif
Binary files differ
diff --git a/Docs/Flags/estonia.txt b/Docs/Flags/estonia.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/estonia.txt
diff --git a/Docs/Flags/finland.eps b/Docs/Flags/finland.eps
new file mode 100644
index 00000000000..c88fa4e2eaa
--- /dev/null
+++ b/Docs/Flags/finland.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f2f2f2f2f2f2f2eb18181825f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2
+f5f5f5f5f5f5f5f3b5b5b5b9f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+191919191919191918181818191919191919191919191919191919191919
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+222222222222222218181819222222222222222222222222222222222222
+b8b8b8b8b8b8b8b8b5b5b5b5b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8b8
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f018181825f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f5b5b5b5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/finland.gif b/Docs/Flags/finland.gif
new file mode 100644
index 00000000000..a43a398f8f1
--- /dev/null
+++ b/Docs/Flags/finland.gif
Binary files differ
diff --git a/Docs/Flags/finland.txt b/Docs/Flags/finland.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/finland.txt
diff --git a/Docs/Flags/france.eps b/Docs/Flags/france.eps
new file mode 100644
index 00000000000..6367b8b98ca
--- /dev/null
+++ b/Docs/Flags/france.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+08080808080808080814f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/france.gif b/Docs/Flags/france.gif
new file mode 100644
index 00000000000..13fcbf29e66
--- /dev/null
+++ b/Docs/Flags/france.gif
Binary files differ
diff --git a/Docs/Flags/france.txt b/Docs/Flags/france.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/france.txt
diff --git a/Docs/Flags/germany.eps b/Docs/Flags/germany.eps
new file mode 100755
index 00000000000..568543e3680
--- /dev/null
+++ b/Docs/Flags/germany.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+464646464646464646464646464646464646464646464646464646464646
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+999999999999999999999999999999999999999999999999999999999999
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/germany.gif b/Docs/Flags/germany.gif
new file mode 100644
index 00000000000..e25a855b3d2
--- /dev/null
+++ b/Docs/Flags/germany.gif
Binary files differ
diff --git a/Docs/Flags/germany.txt b/Docs/Flags/germany.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/germany.txt
diff --git a/Docs/Flags/great-britain.eps b/Docs/Flags/great-britain.eps
new file mode 100755
index 00000000000..97a7ffc9b57
--- /dev/null
+++ b/Docs/Flags/great-britain.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+cfd85508080808080808080811e4c6c6d70808080808080808080967decd
+2db24f000000000000000000099600009f0000000000000000000162ab20
+2ec2cab5b5b5b5b5b5b5b5b5b8970000aeb5b5b5b5b5b5b5b5b5b5cfb520
+ccc7dfa31b0808080808080811e4c6c6d7080808080808080825b4dbc6ce
+1c057a9c1300000000000000099600009f00000000000000001ea8670127
+1c057bdbbab5b5b5b5b5b5b5b8970000aeb5b5b5b5b5b5b5b5bdda670127
+edd9c6cfd85508080808080811e4c6c6d70808080808080967decdc7dde9
+e160012eb14f000000000000099600009f0000000000000162ab200373e3
+e760012ec2cab5b5b5b5b5b5b8970000aeb5b5b5b5b5b5b5cfb5210374ec
+2fc4e9ccc7dea31b0808080811e4c6c6d7080808080825b4dbc6ceedb423
+28c2b21c057a9c1300000000099600009f00000000001ea8670129c2b21c
+c0e9b21c057adabab5b5b5b5b8970000aeb5b5b5b5b5bdd9670129c2e4bc
+080b78edd9c6cfd85508080811e4c6c6d70808080967ddccc7dde8650908
+000373e160012db14f000000099600009f0000000162aa200373e1600100
+b5b6d4e760012dc1cab5b5b5b8970000aeb5b5b5b5cfb4200374eccfb5b5
+0808082fc4e9ccc7dea31b0811e4c6c6d7080825b4dac6ceedb423080808
+00000029c2b21d05799c1300099600009f00001ea8660129c2b21c000000
+b5b5b5c0e9b21d057adabab5b8970000aeb5b5bdd9660129c2e4bdb5b5b5
+080808080b78edd9c6cfd85511e4c6c6d70967ddccc7dde8650908080808
+000000000473e161012db14f099600009f0162aa200474e1600100000000
+b5b5b5b5b6d4e761012dc1cab8970000aeb5cfb4200475eccfb5b5b5b5b5
+0e0e0e0e0e0e35c9eaccc8dfaae4c6c6deb4dcc7cfedb9290e0e0e0e0e0e
+0606060606062ec7b31f0b7fa3960000a7aa6c072bc3b722060606060606
+b7b7b7b7b7b7c2eab31f0b7fde970000b0db6c072bc3e6beb7b7b7b7b7b7
+e4e4e4e4e4e4e4e4e5e5e5e5e5d9c6c6dde5e5e5e5e5e4e4e4e4e4e4e4e4
+9a9a9a9a9a9a9a9a9b9b9a9a9b5e0000709b9a9a9b9b9a9a9a9a9a9a9a9a
+9b9b9b9b9b9b9b9b9b9b9a9a9b5f0000719b9a9a9b9b9b9b9b9b9b9b9b9b
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+dbdbdbdbdbdbdbdfe9e8e6e6e8dbc6c6e0e8e6e6e8e9dddbdbdbdbdbdbdb
+9f9f9f9f9f9f9fa3aea79f9fab6a00007eaa9f9fa8aea19f9f9f9f9f9f9f
+abababababababacafa8a0a0ac6b00007faba0a0a9afacababababababab
+0808080808083ed2e6cac8e098e4c6c6dda3dec7cceac42f080808080808
+00000000000037d1a0120a8b93960000a59c79051db3c228000000000000
+b5b5b5b5b5b5c4eda0130a8ddb970000b0db7a051db3e9c0b5b5b5b5b5b5
+08080808108af0d6c6d2d04411e4c6c6d70855d8cfc6d9ed780b08080808
+000000000887dd4e003cb33d099600009f004fb12d0161e2730300000000
+b5b5b5b5b7d9df4e003cccc5b8970000aeb5cac12d0161e7d4b6b5b5b5b5
+0808083ed2e6cac8e091130811e4c6c6d708081aa3dec7cce9c42f080808
+00000037d09f120a8b8c0b00099600009f0000139c79051db2c228000000
+b5b5b5c4ec9f130b8dd9b8b5b8970000aeb5b5badb7a051db2e9c0b5b5b5
+08108bf0d5c6d2d04408080811e4c6c6d70808080855d8cfc6d9ed780b08
+000887dd4d003cb33e000000099600009f000000004fb12d0160e1730300
+b5b7d9df4d003cccc5b5b5b5b8970000aeb5b5b5b5cac12d0160e7d4b6b5
+3dd2e6cac8e191130808080811e4c6c6d708080808081ba3dec7cce9c42f
+37d09f120b8c8c0b00000000099600009f0000000000139c7a051cb2c229
+c4ec9f120b8dd9b8b5b5b5b5b8970000aeb5b5b5b5b5badb7a051cb2e9c0
+f0d6c6d2d04408080808080811e4c6c6d70808080808080855d8cfc6d9ee
+dd4d003db43d000000000000099600009f000000000000004fb12e0160e3
+df4d003dccc5b5b5b5b5b5b5b8970000aeb5b5b5b5b5b5b5cac22e0160e7
+cac8e191130808080808080811e4c6c6d708080808080808081ba3dec7cb
+120b8c8c0b00000000000000099600009f0000000000000000139c7a051a
+120b8ed9b8b5b5b5b5b5b5b5b8970000aeb5b5b5b5b5b5b5b5badb7b051a
+d2d24408080808080808080811e4c6c6d70808080808080808080855dacf
+3bb63e000000000000000000099600009f000000000000000000004fb32c
+3bcdc5b5b5b5b5b5b5b5b5b5b8970000aeb5b5b5b5b5b5b5b5b5b5cac32c
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/great-britain.gif b/Docs/Flags/great-britain.gif
new file mode 100644
index 00000000000..0f555d078b3
--- /dev/null
+++ b/Docs/Flags/great-britain.gif
Binary files differ
diff --git a/Docs/Flags/great-britain.txt b/Docs/Flags/great-britain.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/great-britain.txt
diff --git a/Docs/Flags/greece.eps b/Docs/Flags/greece.eps
new file mode 100644
index 00000000000..3c022139c56
--- /dev/null
+++ b/Docs/Flags/greece.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+1818181897f7a61818181818181818181818181818181818181818181818
+b5b5b5b5daf7dfb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefeff4f7f4efefefefefefefefefefefefefefefefefefefefefefef
+1818181897f7a61818181818181818181818181818181818181818181818
+b5b5b5b5daf7dfb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefeff4f7f4efefefefefefefefefefefefefefefefefefefefefefef
+1818181897f7a618181818bbc7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7
+b5b5b5b5daf7dfb5b5b5b5e5e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9
+efefefeff4f7f4efefefeff5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5
+1818181897f7a618181818e7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5b5daf7dfb5b5b5b5f2f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+efefefeff4f7f4efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+97979797cdf7d49797979777767676767676767676767676767676767676
+dadadadaeaf7ecdadadadad1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1
+f4f4f4f4f6f7f6f4f4f4f4f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2
+f7f7f7f7f7f7f7f7f7f7f725181818181818181818181818181818181818
+f7f7f7f7f7f7f7f7f7f7f7b9b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+f7f7f7f7f7f7f7f7f7f7f7efefefefefefefefefefefefefefefefefefef
+a6a6a6a6d4f7daa6a6a6a66a676767676767676767676767676767676767
+dfdfdfdfedf7eedfdfdfdfcdcccccccccccccccccccccccccccccccccccc
+f4f4f4f4f6f7f6f4f4f4f4f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2
+1818181897f7a618181818e7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b5b5b5daf7dfb5b5b5b5f2f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+efefefeff4f7f4efefefeff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+1818181897f7a618181818c9d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6
+b5b5b5b5daf7dfb5b5b5b5e9edededededededededededededededededed
+efefefeff4f7f4efefefeff6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+1818181897f7a61818181818181818181818181818181818181818181818
+b5b5b5b5daf7dfb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefeff4f7f4efefefefefefefefefefefefefefefefefefefefefefef
+1818181897f7a61818181818181818181818181818181818181818181818
+b5b5b5b5daf7dfb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefeff4f7f4efefefefefefefefefefefefefefefefefefefefefefef
+e7e7e7e7f0f7f1e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7
+f2f2f2f2f5f7f5f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+555555555555555555555555555555555555555555555555555555555555
+c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7
+f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+878787878787878787878787878787878787878787878787878787878787
+d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6
+f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6b6
+e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4
+f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/greece.gif b/Docs/Flags/greece.gif
new file mode 100644
index 00000000000..1ede215a373
--- /dev/null
+++ b/Docs/Flags/greece.gif
Binary files differ
diff --git a/Docs/Flags/greece.txt b/Docs/Flags/greece.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/greece.txt
diff --git a/Docs/Flags/hungary.eps b/Docs/Flags/hungary.eps
new file mode 100755
index 00000000000..e405fc3cffe
--- /dev/null
+++ b/Docs/Flags/hungary.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7
+575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+464646464646464646464646464646464646464646464646464646464646
+c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8
+464646464646464646464646464646464646464646464646464646464646
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/hungary.gif b/Docs/Flags/hungary.gif
new file mode 100644
index 00000000000..eca0e109bbe
--- /dev/null
+++ b/Docs/Flags/hungary.gif
Binary files differ
diff --git a/Docs/Flags/hungary.txt b/Docs/Flags/hungary.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/hungary.txt
diff --git a/Docs/Flags/iceland.eps b/Docs/Flags/iceland.eps
new file mode 100644
index 00000000000..c2a5529eb42
--- /dev/null
+++ b/Docs/Flags/iceland.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0e0e0e0e0e0e0e15eec6c6e40e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e
+060606060606060ec60000cb060606060606060606060606060606060606
+b7b7b7b7b7b7b7b9c70000d6b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7
+ecececececececece6c6c6e9ecececececececececececececececececec
+c5c5c5c5c5c5c5c59f0000aec5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5
+c6c6c6c6c6c6c6c6a00000afc6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+e6e6e6e6e6e6e6e6e9c6c6ebe6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6e6
+cecececececececeae0000becececececececececececececececececece
+d7d7d7d7d7d7d7d7af0000c0d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080feec6c6e3080808080808080808080808080808080808
+0000000000000008c60000cb000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7c70000d6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/iceland.gif b/Docs/Flags/iceland.gif
new file mode 100644
index 00000000000..ee4d17f5d04
--- /dev/null
+++ b/Docs/Flags/iceland.gif
Binary files differ
diff --git a/Docs/Flags/iceland.txt b/Docs/Flags/iceland.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/iceland.txt
diff --git a/Docs/Flags/ireland.eps b/Docs/Flags/ireland.eps
new file mode 100644
index 00000000000..610b2086fd7
--- /dev/null
+++ b/Docs/Flags/ireland.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f8ffffffffffffffffffff
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7f4d6d6d6d6d6d6d6d6d6d6
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/ireland.gif b/Docs/Flags/ireland.gif
new file mode 100644
index 00000000000..a550678761f
--- /dev/null
+++ b/Docs/Flags/ireland.gif
Binary files differ
diff --git a/Docs/Flags/ireland.txt b/Docs/Flags/ireland.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/ireland.txt
diff --git a/Docs/Flags/island.eps b/Docs/Flags/island.eps
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/island.eps
diff --git a/Docs/Flags/island.gif b/Docs/Flags/island.gif
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/island.gif
diff --git a/Docs/Flags/island.txt b/Docs/Flags/island.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/island.txt
diff --git a/Docs/Flags/israel.eps b/Docs/Flags/israel.eps
new file mode 100755
index 00000000000..3d3059a907a
--- /dev/null
+++ b/Docs/Flags/israel.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0
+f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4
+edededededededededededededededededededededededededededededed
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7a5bef7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7dfe6f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f4f5f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f2ede4807aebedf3f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f5f4f1d4d2f3f4f6f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f3f3f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7c65e5296915755daf7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7e9cac6dbd9c8c7eef7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f5f2f1f4f4f2f1f6f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7809af7f78a90f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7d4dcf7f7d7d9f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f3f4f7f7f3f3f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f77d94f7f7868bf7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7d3daf7f7d6d7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f3f3f7f7f3f3f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7c15e508a835755d6f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7e7cac6d7d5c8c7edf7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f5f1f1f3f3f1f1f6f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f0837ef6f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f5d5d3f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f3f3f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7afc7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7e2e9f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f4f5f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2
+e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7
+f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+bcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbc
+e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5e5
+f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/israel.gif b/Docs/Flags/israel.gif
new file mode 100644
index 00000000000..f7cc613e27d
--- /dev/null
+++ b/Docs/Flags/israel.gif
Binary files differ
diff --git a/Docs/Flags/israel.txt b/Docs/Flags/israel.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/israel.txt
diff --git a/Docs/Flags/italy.eps b/Docs/Flags/italy.eps
new file mode 100755
index 00000000000..20c7c7d5da3
--- /dev/null
+++ b/Docs/Flags/italy.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5b8f7f7f7f7f7f7f7f7f7e400000000000000000000
+0000000000000000000cf7f7f7f7f7f7f7f7f7e400000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/italy.gif b/Docs/Flags/italy.gif
new file mode 100644
index 00000000000..511dba800c7
--- /dev/null
+++ b/Docs/Flags/italy.gif
Binary files differ
diff --git a/Docs/Flags/italy.txt b/Docs/Flags/italy.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/italy.txt
diff --git a/Docs/Flags/japan.eps b/Docs/Flags/japan.eps
new file mode 100755
index 00000000000..8dee6e497ba
--- /dev/null
+++ b/Docs/Flags/japan.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7edddd6d7dfeff7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7c17652557cccf7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7c27653557cccf7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f2d4c6c6c6c6c6c6d8f4f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7de4500000000000157e9f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7de4600000000000158e9f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f2ccc6c6c6c6c6c6c6c6d0f5f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7de1f000000000000000030eaf7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7de1f000000000000000030eaf7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7d4c6c6c6c6c6c6c6c6c6c6d9f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7430000000000000000000060f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7440000000000000000000060f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7ecc6c6c6c6c6c6c6c6c6c6c6c7f1f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7be000000000000000000000003d8f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7be000000000000000000000003d9f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7ddc6c6c6c6c6c6c6c6c6c6c6c6e2f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7720000000000000000000000008ff7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7720000000000000000000000008ff7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7d6c6c6c6c6c6c6c6c6c6c6c6c6dbf7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f74e0000000000000000000000006bf7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f74e0000000000000000000000006bf7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7d6c6c6c6c6c6c6c6c6c6c6c6c6dcf7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f74f0000000000000000000000006cf7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f74f0000000000000000000000006df7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7dec6c6c6c6c6c6c6c6c6c6c6c6e3f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f77600000000000000000000000093f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f77600000000000000000000000093f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7edc6c6c6c6c6c6c6c6c6c6c6c7f2f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7c6000000000000000000000005def7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7c6000000000000000000000005def7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7d6c6c6c6c6c6c6c6c6c6c6dcf7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f74f000000000000000000006cf7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f74f000000000000000000006df7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f4cec6c6c6c6c6c6c6c6d2f5f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7e52a00000000000000003deff7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7e52a00000000000000003deff7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f4d8c6c6c6c6c6c7dbf5f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7e7580200000000056aeff7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7e7590200000000056beff7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f0e1dadbe3f2f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7d389666890dcf7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7d389666890dcf7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/japan.gif b/Docs/Flags/japan.gif
new file mode 100644
index 00000000000..37ebca66f04
--- /dev/null
+++ b/Docs/Flags/japan.gif
Binary files differ
diff --git a/Docs/Flags/japan.txt b/Docs/Flags/japan.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/japan.txt
diff --git a/Docs/Flags/kroatia.eps b/Docs/Flags/kroatia.eps
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/kroatia.eps
diff --git a/Docs/Flags/kroatia.gif b/Docs/Flags/kroatia.gif
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/kroatia.gif
diff --git a/Docs/Flags/kroatia.txt b/Docs/Flags/kroatia.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/kroatia.txt
diff --git a/Docs/Flags/netherlands.eps b/Docs/Flags/netherlands.eps
new file mode 100644
index 00000000000..6f4d9906a11
--- /dev/null
+++ b/Docs/Flags/netherlands.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7d7
+575757575757575757575757575757575757575757575757575757575757
+575757575757575757575757575757575757575757575757575757575757
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c
+464646464646464646464646464646464646464646464646464646464646
+c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/netherlands.gif b/Docs/Flags/netherlands.gif
new file mode 100644
index 00000000000..c09d3eb495c
--- /dev/null
+++ b/Docs/Flags/netherlands.gif
Binary files differ
diff --git a/Docs/Flags/netherlands.txt b/Docs/Flags/netherlands.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/netherlands.txt
diff --git a/Docs/Flags/poland.eps b/Docs/Flags/poland.eps
new file mode 100644
index 00000000000..40d4363a515
--- /dev/null
+++ b/Docs/Flags/poland.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0
+f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+010101010101010101010101010101010101010101010101010101010101
+010101010101010101010101010101010101010101010101010101010101
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/poland.gif b/Docs/Flags/poland.gif
new file mode 100644
index 00000000000..756f9398ee3
--- /dev/null
+++ b/Docs/Flags/poland.gif
Binary files differ
diff --git a/Docs/Flags/poland.txt b/Docs/Flags/poland.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/poland.txt
diff --git a/Docs/Flags/portugal.eps b/Docs/Flags/portugal.eps
new file mode 100644
index 00000000000..7bd24809850
--- /dev/null
+++ b/Docs/Flags/portugal.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+0000000000000000000ac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+0000000000000000000ac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+0000000000000000000ac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+0000000000000000000ac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+00000000000000033b6cd2cac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b4bcc16033010000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+00000000000035c390a0dbe0e5cac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5badfd4d58e93ba2900000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+000000000035e6bf77a5cdbed1eac9c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5bae6bb5194581086da26000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+0000000003c33fe2c4b7b8c8e0e3e0c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b4dfb8973e68614691b7b2000000000000000000000000000000
+0000000000000000342f302f000000000000000000000000000000000000
+000000003b904ebae65668e2bde5dec7c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5bcd4bf04e05064cd12b7b1240000000000000000000000000000
+0000000000000000e0cbd0cd000000000000000000000000000000000000
+0000000065dd91d658222963d7dad7d2c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5c4e4d26e501b2252737b7d530000000000000000000000000000
+0000000000000000b8bcbea8000000000000000000000000000000000000
+0000000064d0c8e363272e6ededaefcec6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5c4dbdb9a5b2027618c9aea4d0000000000000000000000000000
+0000000000000000babdc0aa000000000000000000000000000000000000
+00000000369700a6d95668d5bedce4c5c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5bad6b511a75064941e85bc1e0000000000000000000000000000
+00000000000000009bcbd088000000000000000000000000000000000000
+0000000001ba8fc8f7939df6d0cde3c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b4d7d097ce3f4fca874fae000000000000000000000000000000
+000000000000000006484503000000000000000000000000000000000000
+00000000002bdfc497a3bcd8e4e8c8c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b9e1dca73124a9d0d31e000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+00000000000029b9a3abdee3e3c8c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b9dcd9d89aa6ae1d00000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+00000000000000002859cfc7c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b7bb4d20000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+0000000000000000000ac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+0000000000000000000ac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+0000000000000000000ac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+0000000000000000000ac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/portugal.gif b/Docs/Flags/portugal.gif
new file mode 100644
index 00000000000..91bf32addb2
--- /dev/null
+++ b/Docs/Flags/portugal.gif
Binary files differ
diff --git a/Docs/Flags/portugal.txt b/Docs/Flags/portugal.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/portugal.txt
diff --git a/Docs/Flags/romania.eps b/Docs/Flags/romania.eps
new file mode 100644
index 00000000000..03b53f502a1
--- /dev/null
+++ b/Docs/Flags/romania.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+08080808080808080815fffffffffffffffffffac6c6c6c6c6c6c6c6c6c6
+0000000000000000000dffffffffffffffffffe800000000000000000000
+b5b5b5b5b5b5b5b5b5ab0000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/romania.gif b/Docs/Flags/romania.gif
new file mode 100644
index 00000000000..2d38df262bf
--- /dev/null
+++ b/Docs/Flags/romania.gif
Binary files differ
diff --git a/Docs/Flags/romania.txt b/Docs/Flags/romania.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/romania.txt
diff --git a/Docs/Flags/russia.eps b/Docs/Flags/russia.eps
new file mode 100755
index 00000000000..85c5899d891
--- /dev/null
+++ b/Docs/Flags/russia.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3
+a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0
+e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+080808080808080808080808080808080808080808080808080808080808
+000000000000000000000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+909090909090909090909090909090909090909090909090909090909090
+000000000000000000000000000000000000000000000000000000000000
+333333333333333333333333333333333333333333333333333333333333
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/russia.gif b/Docs/Flags/russia.gif
new file mode 100644
index 00000000000..f72e7f78da6
--- /dev/null
+++ b/Docs/Flags/russia.gif
Binary files differ
diff --git a/Docs/Flags/russia.txt b/Docs/Flags/russia.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/russia.txt
diff --git a/Docs/Flags/singapore.eps b/Docs/Flags/singapore.eps
new file mode 100644
index 00000000000..bc5faf248a7
--- /dev/null
+++ b/Docs/Flags/singapore.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+c6c6c6c6c6cbc9c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+0000000001180d0000000000000000000000000000000000000000000000
+0000000001180e0000000000000000000000000000000000000000000000
+c6c6c6d7ecd6c7c6c8c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+00000054bd5004000b000000000000000000000000000000000000000000
+00000054bd5004000b000000000000000000000000000000000000000000
+c6c6d8f4cdc6c6c8e9ccc6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000059e72200000aae1f0000000000000000000000000000000000000000
+000059e72200000aae1f0000000000000000000000000000000000000000
+c6c7f3dfc6c7c9c6cfc8c6cac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+0004e07d000410002c0b0015000000000000000000000000000000000000
+0004e07d000410002d0b0015000000000000000000000000000000000000
+c6cff7d2c6dbe0c6c6c6d6e5c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+002af73e0067830000004d9b010000000000000000000000000000000000
+002bf73f0067830000004e9c010000000000000000000000000000000000
+c6cef7d3c6c9c9c6c6c6c9c9c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+0029f740000d0d0000000d0d000000000000000000000000000000000000
+0029f740000d0d0000000d0d000000000000000000000000000000000000
+c6c7f2e0c6c6c7c9c6c6cac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+0003dd810000060e00001500000000000000000000000000000000000000
+0003dd810000060e00001500000000000000000000000000000000000000
+c6c6d7f4cec6dcdfc6d4e6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000052e927006c7e0048a102000000000000000000000000000000000000
+000053e927006d7e0048a102000000000000000000000000000000000000
+c6c6c6d5ebd8cbc9c6c9c9c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+0000004bb859160d000d0e00000000000000000000000000000000000000
+0000004bb85a160d000d0e00000000000000000000000000000000000000
+c8c8c8c8c8cbcac8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8
+070707070716100707070707070707070707070707070707070707070707
+070707070716100707070707070707070707070707070707070707070707
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/singapore.gif b/Docs/Flags/singapore.gif
new file mode 100644
index 00000000000..7fbd3f87f62
--- /dev/null
+++ b/Docs/Flags/singapore.gif
Binary files differ
diff --git a/Docs/Flags/singapore.txt b/Docs/Flags/singapore.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/singapore.txt
diff --git a/Docs/Flags/south-africa.eps b/Docs/Flags/south-africa.eps
new file mode 100644
index 00000000000..702df9d4e6a
--- /dev/null
+++ b/Docs/Flags/south-africa.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+0000001fb8e6cac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5bde6a3140000000000000000000000000000000000000000000000
+0000001fb8a4140000000000000000000000000000000000000000000000
+000000000169e9d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5d1df5100000000000000000000000000000000000000000000
+000000000169d85100000000000000000000000000000000000000000000
+00000000000023bde6cac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5bee8a3140000000000000000000000000000000000000000
+00000000000023bda3140000000000000000000000000000000000000000
+080000000000000370ebd6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b7b5b5b5b5b5b5b6d3df5100000000000000000000000000000000000000
+000000000000000370da5100000000000000000000000000000000000000
+db480000000000000028c3e6cac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+f5cab5b5b5b5b5b5b5c0e9a3140000000000000000000000000000000000
+00000000000000000028c3a3140000000000000000000000000000000000
+4bddac1d0000000000000477edd6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+4bdde7bdb5b5b5b5b5b5b6d5e05100000000000000000000000000000000
+000000000000000000000477dc5100000000000000000000000000000000
+000982eb74050000000000002dc8e6d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8
+000982f4d7b6b5b5b5b5b5b5c1eaa45a5a5a5a5a5a5a5a5a5a5a5a5a5a5a
+0000000000000000000000002dc8a45a5a5a5a5a5a5a5a5a5a5a5a5a5a5a
+00000025b8d23d00000000000005769f9f9f9f9f9f9f9f9f9f9f9f9f9f9f
+00000025b8f2c7b5b5b5b5b5b5b6d5e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0
+0000000000000000000000000005769f9f9f9f9f9f9f9f9f9f9f9f9f9f9f
+000000000054e19f15000000000000000000000000000000000000000000
+000000000054e2e3bbb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+0000000000000c8ae9670100000000000000000000000000000000000000
+0000000000000c8af6d3b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000159ee1530000000000000000000000000000000000000000
+000000000000159ef6cdb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000268e88b0c000000000000000000000000000000000000000000
+000000000268ecdeb9b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+00000034cac22c0000000000000b89b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3
+00000034caedc2b5b5b5b5b5b5b8dae5e5e5e5e5e5e5e5e5e5e5e5e5e5e5
+000000000000000000000000000b89b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3
+001195e760010000000000003cd4944c4c4c4c4c4c4c4c4c4c4c4c4c4c4c
+001195f6d1b5b5b5b5b5b5b5c5ed90464646464646464646464646464646
+0000000000000000000000003cd5dcc8c8c8c8c8c8c8c8c8c8c8c8c8c8c8
+5fe79812000000000000098ad64508080808080808080808080808080808
+5fe8e1bab5b5b5b5b5b5b7dad63f00000000000000000000000000000000
+00000000000000000000098aecc6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+cd360000000000000036cf93130808080808080808080808080808080808
+f1c5b5b5b5b5b5b5b5c4eb900c0000000000000000000000000000000000
+00000000000000000036d1dcb8b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+030000000000000783d54508080808080808080808080808080808080808
+b6b5b5b5b5b5b5b7d8d63f00000000000000000000000000000000000000
+000000000000000783ebc6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+00000000000031cb94140808080808080808080808080808080808080808
+b5b5b5b5b5b5c2ea910c0000000000000000000000000000000000000000
+00000000000031ccdcb8b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+00000000057dd44608080808080808080808080808080808080808080808
+b5b5b5b5b6d6d64000000000000000000000000000000000000000000000
+00000000057deac6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0000002ac795140808080808080808080808080808080808080808080808
+b5b5b5c0ea920c0000000000000000000000000000000000000000000000
+0000002ac7dcb8b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/south-africa.gif b/Docs/Flags/south-africa.gif
new file mode 100644
index 00000000000..7fd4ced4469
--- /dev/null
+++ b/Docs/Flags/south-africa.gif
Binary files differ
diff --git a/Docs/Flags/south-africa.txt b/Docs/Flags/south-africa.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/south-africa.txt
diff --git a/Docs/Flags/south-africa1.eps b/Docs/Flags/south-africa1.eps
new file mode 100644
index 00000000000..702df9d4e6a
--- /dev/null
+++ b/Docs/Flags/south-africa1.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+0000001fb8e6cac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5bde6a3140000000000000000000000000000000000000000000000
+0000001fb8a4140000000000000000000000000000000000000000000000
+000000000169e9d6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5d1df5100000000000000000000000000000000000000000000
+000000000169d85100000000000000000000000000000000000000000000
+00000000000023bde6cac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b5b5b5b5b5b5bee8a3140000000000000000000000000000000000000000
+00000000000023bda3140000000000000000000000000000000000000000
+080000000000000370ebd6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+b7b5b5b5b5b5b5b6d3df5100000000000000000000000000000000000000
+000000000000000370da5100000000000000000000000000000000000000
+db480000000000000028c3e6cac6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+f5cab5b5b5b5b5b5b5c0e9a3140000000000000000000000000000000000
+00000000000000000028c3a3140000000000000000000000000000000000
+4bddac1d0000000000000477edd6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+4bdde7bdb5b5b5b5b5b5b6d5e05100000000000000000000000000000000
+000000000000000000000477dc5100000000000000000000000000000000
+000982eb74050000000000002dc8e6d8d8d8d8d8d8d8d8d8d8d8d8d8d8d8
+000982f4d7b6b5b5b5b5b5b5c1eaa45a5a5a5a5a5a5a5a5a5a5a5a5a5a5a
+0000000000000000000000002dc8a45a5a5a5a5a5a5a5a5a5a5a5a5a5a5a
+00000025b8d23d00000000000005769f9f9f9f9f9f9f9f9f9f9f9f9f9f9f
+00000025b8f2c7b5b5b5b5b5b5b6d5e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0
+0000000000000000000000000005769f9f9f9f9f9f9f9f9f9f9f9f9f9f9f
+000000000054e19f15000000000000000000000000000000000000000000
+000000000054e2e3bbb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+0000000000000c8ae9670100000000000000000000000000000000000000
+0000000000000c8af6d3b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000000159ee1530000000000000000000000000000000000000000
+000000000000159ef6cdb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+000000000268e88b0c000000000000000000000000000000000000000000
+000000000268ecdeb9b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+000000000000000000000000000000000000000000000000000000000000
+00000034cac22c0000000000000b89b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3
+00000034caedc2b5b5b5b5b5b5b8dae5e5e5e5e5e5e5e5e5e5e5e5e5e5e5
+000000000000000000000000000b89b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3
+001195e760010000000000003cd4944c4c4c4c4c4c4c4c4c4c4c4c4c4c4c
+001195f6d1b5b5b5b5b5b5b5c5ed90464646464646464646464646464646
+0000000000000000000000003cd5dcc8c8c8c8c8c8c8c8c8c8c8c8c8c8c8
+5fe79812000000000000098ad64508080808080808080808080808080808
+5fe8e1bab5b5b5b5b5b5b7dad63f00000000000000000000000000000000
+00000000000000000000098aecc6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+cd360000000000000036cf93130808080808080808080808080808080808
+f1c5b5b5b5b5b5b5b5c4eb900c0000000000000000000000000000000000
+00000000000000000036d1dcb8b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+030000000000000783d54508080808080808080808080808080808080808
+b6b5b5b5b5b5b5b7d8d63f00000000000000000000000000000000000000
+000000000000000783ebc6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+00000000000031cb94140808080808080808080808080808080808080808
+b5b5b5b5b5b5c2ea910c0000000000000000000000000000000000000000
+00000000000031ccdcb8b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+00000000057dd44608080808080808080808080808080808080808080808
+b5b5b5b5b6d6d64000000000000000000000000000000000000000000000
+00000000057deac6b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0000002ac795140808080808080808080808080808080808080808080808
+b5b5b5c0ea920c0000000000000000000000000000000000000000000000
+0000002ac7dcb8b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/south-africa1.gif b/Docs/Flags/south-africa1.gif
new file mode 100644
index 00000000000..7fd4ced4469
--- /dev/null
+++ b/Docs/Flags/south-africa1.gif
Binary files differ
diff --git a/Docs/Flags/south-africa1.txt b/Docs/Flags/south-africa1.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/south-africa1.txt
diff --git a/Docs/Flags/south-korea.eps b/Docs/Flags/south-korea.eps
new file mode 100755
index 00000000000..a363ab514c4
--- /dev/null
+++ b/Docs/Flags/south-korea.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7eff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f5f7f7f7f7f7f7
+f7f7f7f7f7f7eff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f5f7f7f7f7f7f7
+f7f7f7f7f7f7eff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f5f7f7f7f7f7f7
+f7f7f7f7f7985ad7f7f7f7f7f7f7f7f7f7f7f7f7f7f7c255d3f7f7f7f7f7
+f7f7f7f7f7985ad7f7f7f7f7f7f7f7f7f7f7f7f7f7f7c255d3f7f7f7f7f7
+f7f7f7f7f7985ad7f7f7f7f7f7f7f7f7f7f7f7f7f7f7c255d3f7f7f7f7f7
+f7f7f7f7d6434363f7f7f7f7f7f7f7f7f7f7f7f7f7f0474476f6f7f7f7f7
+f7f7f7f7d6434363f7f7f7f7f7f7f7f7f7f7f7f7f7f0474476f6f7f7f7f7
+f7f7f7f7d6434363f7f7f7f7f7f7f7f7f7f7f7f7f7f0474476f6f7f7f7f7
+f7f7f7f7584345e4f7f7f7f7f7f6f1f1f7f7f7f7f7f7ba5a4391f7f7f7f7
+f7f7f7f7584345e4f7f7f7f7f7f4d7d9f5f7f7f7f7f7ba5a4391f7f7f7f7
+f7f7f7f7584345e4f7f7f7f7f7f4d8d9f5f7f7f7f7f7ba5a4391f7f7f7f7
+f7f7f7f7d65ab0f7f7f7f7f5decac6c6cbe0f6f7f7f7f76570dcf7f7f7f7
+f7f7f7f7d65ab0f7f7f7f7ef791300001884f3f7f7f7f76570dcf7f7f7f7
+f7f7f7f7d65ab0f7f7f7f7ef791300001885f3f7f7f7f76570dcf7f7f7f7
+f7f7f7f7f7f3f7f7f7f7f5d2c6c6c6c6c6c6d6f7f7f7f7ecf4f7f7f7f7f7
+f7f7f7f7f7f3f7f7f7f7ed3a0000000000004ef4f7f7f7ecf4f7f7f7f7f7
+f7f7f7f7f7f3f7f7f7f7ed3a0000000000004ef4f7f7f7ecf4f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7d9c6c6c6c6c6c6c6c6e3f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f76c00000000000000008ff7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f76e00000000000000008ff7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7eebbc6c6c6c6bc68548ecef7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7ee0a000000000000000026f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f41600000000095a6d3526f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7c8b1c6c6c6c53908080875f5f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7c600000000000000000001eaf7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7ea140000000187b5b5b54eeaf7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7c75fc6c6c66a080808082cf4f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7c500000000000000000000e7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7ea6300000058b5b5b5b593e8f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7ed114b6b36080808080838f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7ed0900000000000000001df7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f4b7755789b5b5b5b5b5a9f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f76b080808080808080884f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f76600000000000000007ef7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7d0b5b5b5b5b5b5b5b5d5f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7eef6f7f7f7ea3508080808080844f1f7f7f7ecedf7f7f7f7f7
+f7f7f7f7f7eef6f7f7f7e92f0000000000003ef1f7f7f7ecedf7f7f7f7f7
+f7f7f7f7f7eef6f7f7f7f3c1b5b5b5b5b5b5c6f5f7f7f7ecedf7f7f7f7f7
+f7f7f7f7cd569af7f7f7f7eb70140808187bf0f7f7f7f76b60d6f7f7f7f7
+f7f7f7f7cd569af7f7f7f7ea6b0c00001177f0f7f7f7f76b60d6f7f7f7f7
+f7f7f7f7cd569af7f7f7f7f4d2b8b5b5b9d5f5f7f7f7f76b60d6f7f7f7f7
+f7f7f7f7604b52dff7f7f7f7f7f1d0d2f3f7f7f7f7f7b4794787f7f7f7f7
+f7f7f7f7604b52dff7f7f7f7f7f1cfd1f3f7f7f7f7f7b4794787f7f7f7f7
+f7f7f7f7604b52dff7f7f7f7f7f5ecedf6f7f7f7f7f7b4794787f7f7f7f7
+f7f7f7f7e0504563f7f7f7f7f7f7f7f7f7f7f7f7f7f14a4678f5f7f7f7f7
+f7f7f7f7e0504563f7f7f7f7f7f7f7f7f7f7f7f7f7f14a4678f5f7f7f7f7
+f7f7f7f7e0504563f7f7f7f7f7f7f7f7f7f7f7f7f7f14a4678f5f7f7f7f7
+f7f7f7f7f79c64ddf7f7f7f7f7f7f7f7f7f7f7f7f7f7d060d8f7f7f7f7f7
+f7f7f7f7f79c64ddf7f7f7f7f7f7f7f7f7f7f7f7f7f7d060d8f7f7f7f7f7
+f7f7f7f7f79c64ddf7f7f7f7f7f7f7f7f7f7f7f7f7f7d060d8f7f7f7f7f7
+f7f7f7f7f7f7f4f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f4f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f4f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/south-korea.gif b/Docs/Flags/south-korea.gif
new file mode 100644
index 00000000000..0d8630ba963
--- /dev/null
+++ b/Docs/Flags/south-korea.gif
Binary files differ
diff --git a/Docs/Flags/south-korea.txt b/Docs/Flags/south-korea.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/south-korea.txt
diff --git a/Docs/Flags/spain.eps b/Docs/Flags/spain.eps
new file mode 100644
index 00000000000..340fe9c7671
--- /dev/null
+++ b/Docs/Flags/spain.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7
+040404040404040404040404040404040404040404040404040404040404
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfd
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+fcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfc
+f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/spain.gif b/Docs/Flags/spain.gif
new file mode 100644
index 00000000000..9d2e1be0fe7
--- /dev/null
+++ b/Docs/Flags/spain.gif
Binary files differ
diff --git a/Docs/Flags/spain.txt b/Docs/Flags/spain.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/spain.txt
diff --git a/Docs/Flags/sweden.eps b/Docs/Flags/sweden.eps
new file mode 100755
index 00000000000..47cd1fa3e9c
--- /dev/null
+++ b/Docs/Flags/sweden.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0e0e0e0e0e0e0e16fffffff10e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e
+060606060606060efffffff0060606060606060606060606060606060606
+b1b1b1b1b1b1b1ab0000000ab1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1
+fefefefefefefefefffffffffefefefefefefefefefefefefefefefefefe
+fefefefefefefefefffffffffefefefefefefefefefefefefefefefefefe
+010101010101010100000000010101010101010101010101010101010101
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+f3f3f3f3f3f3f3f3fffffffef3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3
+f3f3f3f3f3f3f3f3fffffffef3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3
+080808080808080800000000080808080808080808080808080808080808
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+0808080808080810fffffff1080808080808080808080808080808080808
+0000000000000008fffffff0000000000000000000000000000000000000
+b5b5b5b5b5b5b5af0000000bb5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/sweden.gif b/Docs/Flags/sweden.gif
new file mode 100644
index 00000000000..e16ede8e641
--- /dev/null
+++ b/Docs/Flags/sweden.gif
Binary files differ
diff --git a/Docs/Flags/sweden.txt b/Docs/Flags/sweden.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/sweden.txt
diff --git a/Docs/Flags/switzerland.eps b/Docs/Flags/switzerland.eps
new file mode 100644
index 00000000000..517919e3125
--- /dev/null
+++ b/Docs/Flags/switzerland.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c7c7c7c7c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000404040400000000000000000000000000
+000000000000000000000000000404040400000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c9f7f7f7f4c6c6c6c6c6c6c6c6c6c6c6c6c6
+0000000000000000000000000ff7f7f7e700000000000000000000000000
+00000000000000000000000010f7f7f7e700000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c9f7f7f7f4c6c6c6c6c6c6c6c6c6c6c6c6c6
+0000000000000000000000000ff7f7f7e700000000000000000000000000
+00000000000000000000000010f7f7f7e700000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c9f7f7f7f4c6c6c6c6c6c6c6c6c6c6c6c6c6
+0000000000000000000000000ff7f7f7e700000000000000000000000000
+00000000000000000000000010f7f7f7e700000000000000000000000000
+c6c6c6c6c6c6c6c6c6c8c8c8cbf7f7f7f4c8c8c8c8c6c6c6c6c6c6c6c6c6
+00000000000000000008080817f7f7f7e708080807000000000000000000
+00000000000000000008080817f7f7f7e708080807000000000000000000
+c6c6c6c6c6c6c6c6c9f7f7f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6
+00000000000000000cf7f7f7f7f7f7f7f7f7f7f7e3000000000000000000
+00000000000000000cf7f7f7f7f7f7f7f7f7f7f7e3000000000000000000
+c6c6c6c6c6c6c6c6c9f7f7f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6
+00000000000000000cf7f7f7f7f7f7f7f7f7f7f7e3000000000000000000
+00000000000000000cf7f7f7f7f7f7f7f7f7f7f7e3000000000000000000
+c6c6c6c6c6c6c6c6c9f7f7f7f7f7f7f7f7f7f7f7f3c6c6c6c6c6c6c6c6c6
+00000000000000000cf7f7f7f7f7f7f7f7f7f7f7e3000000000000000000
+00000000000000000cf7f7f7f7f7f7f7f7f7f7f7e3000000000000000000
+c6c6c6c6c6c6c6c6c8f5f5f5f5f7f7f7f7f5f5f5f1c6c6c6c6c6c6c6c6c6
+00000000000000000beeeeeeeff7f7f7f6eeeeeeda000000000000000000
+00000000000000000cefefefeff7f7f7f6efefefdb000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c9f7f7f7f4c6c6c6c6c6c6c6c6c6c6c6c6c6
+0000000000000000000000000ff7f7f7e700000000000000000000000000
+00000000000000000000000010f7f7f7e700000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c9f7f7f7f4c6c6c6c6c6c6c6c6c6c6c6c6c6
+0000000000000000000000000ff7f7f7e700000000000000000000000000
+00000000000000000000000010f7f7f7e700000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c9f7f7f7f4c6c6c6c6c6c6c6c6c6c6c6c6c6
+0000000000000000000000000ff7f7f7e700000000000000000000000000
+00000000000000000000000010f7f7f7e700000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c9f5f5f5f2c6c6c6c6c6c6c6c6c6c6c6c6c6
+0000000000000000000000000feaeaeada00000000000000000000000000
+0000000000000000000000000febebebdb00000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/switzerland.gif b/Docs/Flags/switzerland.gif
new file mode 100644
index 00000000000..98cef7c28d6
--- /dev/null
+++ b/Docs/Flags/switzerland.gif
Binary files differ
diff --git a/Docs/Flags/switzerland.txt b/Docs/Flags/switzerland.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/switzerland.txt
diff --git a/Docs/Flags/taiwan.eps b/Docs/Flags/taiwan.eps
new file mode 100755
index 00000000000..a514bdf2af4
--- /dev/null
+++ b/Docs/Flags/taiwan.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+080808080808081108080808080813c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000900000000000000000000000000000000000000000000
+b5b5b5b5b5b5b5b7b5b5b5b5b5b5aa000000000000000000000000000000
+0808080808490e9e11450808080813c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000043069a0a3f0000000000000000000000000000000000000000
+b5b5b5b5b5c7b7deb8c6b5b5b5b5aa000000000000000000000000000000
+0808080e14658bb28d59170c080813c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000060c6087b089530f04000000000000000000000000000000000000
+b5b5b5b7b8cfd9e4dacbb9b6b5b5aa000000000000000000000000000000
+0808080baba1f7f7f7a0a009080813c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+00000003a89ef7f7f79d9c00000000000000000000000000000000000000
+b5b5b5b6e2dff7f7f7dfdfb5b5b5aa000000000000000000000000000000
+0808082b5becf7f7f7e06025080813c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+0000002456ecf7f7f7df5b1e000000000000000000000000000000000000
+b5b5b5bfccf4f7f7f7f1cdbdb5b5aa000000000000000000000000000000
+0808082556eaf7f7f7de5a20080813c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+0000001e50eaf7f7f7dd5418000000000000000000000000000000000000
+b5b5b5bdcaf3f7f7f7f0ccbcb5b5aa000000000000000000000000000000
+0808080bb099f7f7f799a509080813c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+00000004ad96f7f7f795a201000000000000000000000000000000000000
+b5b5b5b6e3ddf7f7f7dde0b5b5b5aa000000000000000000000000000000
+0808080d0e6b82b2855f100b080813c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+0000000507667eb081590903000000000000000000000000000000000000
+b5b5b5b6b7d0d7e4d7cdb7b6b5b5aa000000000000000000000000000000
+0808080808440c970f410808080813c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+00000000003e0493073b0000000000000000000000000000000000000000
+b5b5b5b5b5c6b6dcb7c5b5b5b5b5aa000000000000000000000000000000
+0e0e0e0e0e0e0e150e0e0e0e0e0e19c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000700000000000000000000000000000000000000000000
+b0b0b0b0b0b0b0b2b0b0b0b0b0b0a6000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+010101010101010101010101010101000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/taiwan.gif b/Docs/Flags/taiwan.gif
new file mode 100644
index 00000000000..5cfc3d46425
--- /dev/null
+++ b/Docs/Flags/taiwan.gif
Binary files differ
diff --git a/Docs/Flags/taiwan.txt b/Docs/Flags/taiwan.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/taiwan.txt
diff --git a/Docs/Flags/ukraine.eps b/Docs/Flags/ukraine.eps
new file mode 100644
index 00000000000..fe2436fa554
--- /dev/null
+++ b/Docs/Flags/ukraine.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+181818181818181818181818181818181818181818181818181818181818
+b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5
+efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f
+b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7
+e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8e8
+fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+010101010101010101010101010101010101010101010101010101010101
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/ukraine.gif b/Docs/Flags/ukraine.gif
new file mode 100644
index 00000000000..b951bef5b2a
--- /dev/null
+++ b/Docs/Flags/ukraine.gif
Binary files differ
diff --git a/Docs/Flags/ukraine.txt b/Docs/Flags/ukraine.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/ukraine.txt
diff --git a/Docs/Flags/usa.eps b/Docs/Flags/usa.eps
new file mode 100755
index 00000000000..31bd9996d11
--- /dev/null
+++ b/Docs/Flags/usa.eps
@@ -0,0 +1,87 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Creator: pnmtops
+%%Title: noname.ps
+%%Pages: 1
+%%BoundingBox: 291 371 320 391
+%%EndComments
+/readstring {
+ currentfile exch readhexstring pop
+} bind def
+/rpicstr 30 string def
+/gpicstr 30 string def
+/bpicstr 30 string def
+%%EndProlog
+%%Page: 1 1
+gsave
+291.6 371.4 translate
+28.8 19.2 scale
+30 20 8
+[ 30 0 0 -20 0 20 ]
+{ rpicstr readstring }
+{ gpicstr readstring }
+{ bpicstr readstring }
+true 3
+colorimage
+182608340a122c08300e0e31082b1ec6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+111f002d020a25002907062a00240b000000000000000000000000000000
+b9bdb5c1b6b8bfb5c0b7b7c0b5bfad000000000000000000000000000000
+1a2422331d182b243117183223291fdcdcdcdcdcdcdcdcdcdcdcdcdcdcdc
+121d1a2c1610241c2a0f112b1c2211717171717171717171717171717171
+babdbcc1bbb9bfbdc0b9b9c0bdbeb4717171717171717171717171717171
+0a134413301e134513262813451316f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+020b3e0c29170b3f0c1f210c3f0c0ff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b8c5b8c0bbb8c6b8bdbeb8c6b8b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+28360e54101b430e4e1212500e4029c9c9c9c9c9c9c9c9c9c9c9c9c9c9c9
+212f064e08133d06480b0a49063a17101010101010101010101010101010
+bec2b7cab7bac5b7c8b8b8c9b7c5b1101010101010101010101010101010
+080e580a3f250b5b0a30340a5b0c14d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9
+00065302391e035603292d02550406616161616161616161616161616161
+b5b7cbb6c4bdb6ccb6c0c1b6ccb6b0616161616161616161616161616161
+2a3d085c0b1b4c0856110f5808492cf7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+233700570313460051090753004325f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+bec4b5ccb6bac8b5cab7b7cbb5c7bff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+080c5d084425096008323708600913cccccccccccccccccccccccccccccc
+000458003e1e015b002b30005a01021f1f1f1f1f1f1f1f1f1f1f1f1f1f1f
+b5b6cdb5c5bdb5cdb5c1c2b5cdb5ac1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f
+293f085e0a1a4e0858100e5a084b29d6d6d6d6d6d6d6d6d6d6d6d6d6d6d6
+22390059021348005308065500451b525252525252525252525252525252
+bec4b5cdb6bac8b5cbb7b7ccb5c7b5525252525252525252525252525252
+080c58094222095b083034085a0a16f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+000452013b1b015500292e0055020ff7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+b5b6cbb5c5bcb5ccb5c0c1b5ccb5b9f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+23370e500d19440e4b12114c0e4224cfcfcfcfcfcfcfcfcfcfcfcfcfcfcf
+1b31064a05113e06450a0946063c132f2f2f2f2f2f2f2f2f2f2f2f2f2f2f
+bcc2b7c9b6bac5b7c7b8b8c8b7c5b22f2f2f2f2f2f2f2f2f2f2f2f2f2f2f
+4f504857484d524856494956485155d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3
+494a425142474d4250434351424c47424242424242424242424242424242
+c9c9c7cbc7c8cac7cbc7c7cbc7c9c1424242424242424242424242424242
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2
+3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e
+3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e3e
+d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0
+323232323232323232323232323232323232323232323232323232323232
+323232323232323232323232323232323232323232323232323232323232
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5
+4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e
+4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e4e
+cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd
+232323232323232323232323232323232323232323232323232323232323
+232323232323232323232323232323232323232323232323232323232323
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7
+d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9
+5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d
+5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d
+c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6
+000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000
+grestore
+showpage
+%%Trailer
diff --git a/Docs/Flags/usa.gif b/Docs/Flags/usa.gif
new file mode 100644
index 00000000000..da9f4e27d6c
--- /dev/null
+++ b/Docs/Flags/usa.gif
Binary files differ
diff --git a/Docs/Flags/usa.txt b/Docs/Flags/usa.txt
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Docs/Flags/usa.txt
diff --git a/Docs/Images/Attic/html-fs.gif b/Docs/Images/Attic/html-fs.gif
new file mode 100644
index 00000000000..73f9ab5bec6
--- /dev/null
+++ b/Docs/Images/Attic/html-fs.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-01.gif b/Docs/Images/Attic/mysql-01.gif
new file mode 100644
index 00000000000..773453f8dd7
--- /dev/null
+++ b/Docs/Images/Attic/mysql-01.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-02.gif b/Docs/Images/Attic/mysql-02.gif
new file mode 100644
index 00000000000..12d984b55e0
--- /dev/null
+++ b/Docs/Images/Attic/mysql-02.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-03.gif b/Docs/Images/Attic/mysql-03.gif
new file mode 100644
index 00000000000..abb16f2aa59
--- /dev/null
+++ b/Docs/Images/Attic/mysql-03.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-04.gif b/Docs/Images/Attic/mysql-04.gif
new file mode 100644
index 00000000000..e207e1790f7
--- /dev/null
+++ b/Docs/Images/Attic/mysql-04.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-05.gif b/Docs/Images/Attic/mysql-05.gif
new file mode 100644
index 00000000000..f78b8a17b93
--- /dev/null
+++ b/Docs/Images/Attic/mysql-05.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-06.gif b/Docs/Images/Attic/mysql-06.gif
new file mode 100644
index 00000000000..c660e1d1f4f
--- /dev/null
+++ b/Docs/Images/Attic/mysql-06.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-07.gif b/Docs/Images/Attic/mysql-07.gif
new file mode 100644
index 00000000000..be309d0de1c
--- /dev/null
+++ b/Docs/Images/Attic/mysql-07.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-08.gif b/Docs/Images/Attic/mysql-08.gif
new file mode 100644
index 00000000000..3d5b2135655
--- /dev/null
+++ b/Docs/Images/Attic/mysql-08.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-09.gif b/Docs/Images/Attic/mysql-09.gif
new file mode 100644
index 00000000000..75d08592795
--- /dev/null
+++ b/Docs/Images/Attic/mysql-09.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-10.gif b/Docs/Images/Attic/mysql-10.gif
new file mode 100644
index 00000000000..8d0a8551e9e
--- /dev/null
+++ b/Docs/Images/Attic/mysql-10.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-11.gif b/Docs/Images/Attic/mysql-11.gif
new file mode 100644
index 00000000000..e5f3770a7bd
--- /dev/null
+++ b/Docs/Images/Attic/mysql-11.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-12.gif b/Docs/Images/Attic/mysql-12.gif
new file mode 100644
index 00000000000..b045aaf3549
--- /dev/null
+++ b/Docs/Images/Attic/mysql-12.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-13.gif b/Docs/Images/Attic/mysql-13.gif
new file mode 100644
index 00000000000..0d5aaf88f6f
--- /dev/null
+++ b/Docs/Images/Attic/mysql-13.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-14.gif b/Docs/Images/Attic/mysql-14.gif
new file mode 100644
index 00000000000..9bce287b4b3
--- /dev/null
+++ b/Docs/Images/Attic/mysql-14.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-15.gif b/Docs/Images/Attic/mysql-15.gif
new file mode 100644
index 00000000000..d70ffec83dd
--- /dev/null
+++ b/Docs/Images/Attic/mysql-15.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-16.gif b/Docs/Images/Attic/mysql-16.gif
new file mode 100644
index 00000000000..9b30833dc1d
--- /dev/null
+++ b/Docs/Images/Attic/mysql-16.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-17.gif b/Docs/Images/Attic/mysql-17.gif
new file mode 100644
index 00000000000..5b228496b66
--- /dev/null
+++ b/Docs/Images/Attic/mysql-17.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-18.gif b/Docs/Images/Attic/mysql-18.gif
new file mode 100644
index 00000000000..71211350aa2
--- /dev/null
+++ b/Docs/Images/Attic/mysql-18.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-19.gif b/Docs/Images/Attic/mysql-19.gif
new file mode 100644
index 00000000000..38e6691d9c6
--- /dev/null
+++ b/Docs/Images/Attic/mysql-19.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql-compatible.jpg b/Docs/Images/Attic/mysql-compatible.jpg
new file mode 100644
index 00000000000..cce9cf84b91
--- /dev/null
+++ b/Docs/Images/Attic/mysql-compatible.jpg
Binary files differ
diff --git a/Docs/Images/Attic/mysql5.gif b/Docs/Images/Attic/mysql5.gif
new file mode 100644
index 00000000000..f78b8a17b93
--- /dev/null
+++ b/Docs/Images/Attic/mysql5.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql_anim-01.gif b/Docs/Images/Attic/mysql_anim-01.gif
new file mode 100644
index 00000000000..f537d60da41
--- /dev/null
+++ b/Docs/Images/Attic/mysql_anim-01.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql_anim-02.gif b/Docs/Images/Attic/mysql_anim-02.gif
new file mode 100644
index 00000000000..cfd3e1cfc3e
--- /dev/null
+++ b/Docs/Images/Attic/mysql_anim-02.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql_anim-03.gif b/Docs/Images/Attic/mysql_anim-03.gif
new file mode 100644
index 00000000000..6ac6b3ebcc1
--- /dev/null
+++ b/Docs/Images/Attic/mysql_anim-03.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql_anim-04.gif b/Docs/Images/Attic/mysql_anim-04.gif
new file mode 100644
index 00000000000..d3150860ecf
--- /dev/null
+++ b/Docs/Images/Attic/mysql_anim-04.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql_anim-05.gif b/Docs/Images/Attic/mysql_anim-05.gif
new file mode 100644
index 00000000000..46f288ef71d
--- /dev/null
+++ b/Docs/Images/Attic/mysql_anim-05.gif
Binary files differ
diff --git a/Docs/Images/Attic/mysql_anim-06.gif b/Docs/Images/Attic/mysql_anim-06.gif
new file mode 100644
index 00000000000..3dc283dbfb6
--- /dev/null
+++ b/Docs/Images/Attic/mysql_anim-06.gif
Binary files differ
diff --git a/Docs/Images/Attic/powered-by-MySQL-transparent.gif b/Docs/Images/Attic/powered-by-MySQL-transparent.gif
new file mode 100644
index 00000000000..be309d0de1c
--- /dev/null
+++ b/Docs/Images/Attic/powered-by-MySQL-transparent.gif
Binary files differ
diff --git a/Docs/Images/empty.png b/Docs/Images/empty.png
new file mode 100644
index 00000000000..71ac39b37f0
--- /dev/null
+++ b/Docs/Images/empty.png
Binary files differ
diff --git a/Docs/Images/flag-background.pnm b/Docs/Images/flag-background.pnm
new file mode 100755
index 00000000000..2bd7b604298
--- /dev/null
+++ b/Docs/Images/flag-background.pnm
Binary files differ
diff --git a/Docs/Images/mysql-logo.gif b/Docs/Images/mysql-logo.gif
new file mode 100644
index 00000000000..c660e1d1f4f
--- /dev/null
+++ b/Docs/Images/mysql-logo.gif
Binary files differ
diff --git a/Docs/LICENSE b/Docs/LICENSE
new file mode 100644
index 00000000000..bd123fe42a5
--- /dev/null
+++ b/Docs/LICENSE
@@ -0,0 +1,98 @@
+ End-User License Agreement for MySQL Commercial Server
+
+ (Version 6, July 13, 2000)
+
+ Copyright (C) 2000, MySQL AB & MySQL Finland AB
+
+ Stockholm SWEDEN, Helsingfors FINLAND and Uppsala SWEDEN
+
+ All rights reserved.
+
+Definitions. This End-User License Agreement ("License") is a legal
+agreement between you, either an individual or a single entity,
+("Licensee") and MySQL AB, MySQL Finland AB and Detron HB ("Licensor")
+for the software product identified above, which includes computer
+software and may include associated media, printed materials, and
+online or electronic documentation ("Software"). The Software also
+includes any updates and supplements to the original Software product
+provided to you by Licensor. Any software provided along with the
+Software that is associated with a separate end-user license agreement
+is licensed to you under the terms of that license agreement.
+
+Agreement to the License. The Software is protected by copyright laws
+and international copyright treaties, as well as other intellectual
+property laws and treaties. The Software is licensed, not sold. If you
+do not agree to the terms of this License, do not install or use the
+Software. By installing, copying, modifying, downloading,
+distributing, accessing or otherwise using the Software, you agree to
+be bound by the following terms of this License:
+
+1. Grant for Authorized Use of the Software
+
+Licensor hereby grants to Licensee a non-exclusive, non-transferable
+right to use the Software in: - Installing. You may install copies of
+the Software for authorized use on your computers, including
+workstations, terminals and other digital electronic devices
+("Computer"). - Single Computer use. You may only use the Software on
+one Computer at a time regardless the number of Computers with
+installed copies. This right covers any number of concurrent users,
+CPUs and MySQL-servers with any number of copies running on one
+Computer.
+
+2. Description of Other Rights
+
+Licensor grants no other rights to the Software except as expressly
+set forth herein:
+
+- Copying. You may not copy the Software unless copies or adaptations
+ are meant for authorized use, archival purposes or when copying or
+ adaptation is a necessary step in the authorized use of the Software.
+
+- Distribution. You may not distribute the Software.
+
+- Modifying. You may modify the Software but you must reproduce all
+ copyright notices in the Software on all modified copies and
+ adaptations.
+
+- License transfer. You may resell or rent this License. If any
+ modifications have been made to the Software, you must include a
+ proper notification that the Software is modified.
+
+- Support services. Licensor may provide you with support services
+ related to the Software. Use and terms of support services are not
+ governed in this License.
+
+3. Term
+
+This license is effective until terminated. Licensor has the
+right to terminate your License immediately if you fail to comply with
+any term of this License.
+
+4. No Warranty
+
+The Software is provided "as is". Licensor makes no warranties,
+express or implied, arising from course of dealing or usage of trade,
+or statutory, as to any matter whatsoever. In particular, any and all
+warranties or merchantability, fitness for a particular purpose or
+non-infringement of third party rights are expressly excluded. The
+entire risk as to the quality and performance of the Software is with
+you. If the Software proves defective, you assume all the cost of
+necessary service, repair or correction.
+
+5. Limited Liability
+
+In no event will Licensor be liable to you for any consequential or
+incidental damages, including any lost profits or lost savings, or for
+any claim by any party, even if a Licensor representative has been
+advised of the possibility of such damages. Some states do not allow
+the exclusion or limitation of liability. Therefore, in any case, the
+entire liability of Licensor under any provision of this License is
+limited to the amount actually paid by you for the Software.
+
+6. Governing Law and Jurisdiction
+
+This License will be governed by the laws in force in
+Sweden. Jurisdiction is with Tingsrätten of Stockholm, Sweden.
+
+Should you have any questions concerning the validity of this License,
+please contact: mysql-licensing@mysql.com.
diff --git a/Docs/Makefile.am b/Docs/Makefile.am
new file mode 100644
index 00000000000..fbe0ca41619
--- /dev/null
+++ b/Docs/Makefile.am
@@ -0,0 +1,120 @@
+# Monty
+
+# Normally you do not need to remake the files here. But if you want
+# to you will need the GNU TeX-info utilities. To make a Postscript
+# files you also need TeX and dvips. To make the PDF file you will
+# need pdftex. We use the teTeX distribution for all of these.
+
+# We avoid default automake rules because of problems with .dvi file
+# and BSD makes
+
+# If you know how to fix any of this more elegantly please mail
+# david@mysql.com
+
+TEXI2HTML_FLAGS = -iso -number
+DVIPS = dvips
+MAKEINFO = @MAKEINFO@
+TEXINFO_TEX = Support/texinfo.tex
+
+noinst_SCRIPTS = Support/texi2html Support/generate-text-files.pl \
+ Support/generate-mirror-listing.pl
+info_TEXINFOS = manual.texi
+
+targets = manual.txt mysql.info manual.html manual.pdf
+
+BUILT_SOURCES = $(targets) manual_toc.html include.texi
+EXTRA_DIST = $(noinst_SCRIPTS) $(BUILT_SOURCES) mysqld_error.txt INSTALL-BINARY
+
+all: $(targets) txt_files
+
+txt_files: ../INSTALL-SOURCE ../COPYING ../COPYING.LIB \
+ ../MIRRORS INSTALL-BINARY
+
+# The PostScript version is so big that is not included in the
+# standard distribution. It is available for download from the home page.
+paper: manual_a4.ps manual_letter.ps
+
+#########################################################################
+
+# The Makefile contains the previous version so we can not use that
+include.texi: ../configure.in
+ echo -n "@c This file is autogenerated by the Makefile" > $@
+ echo -n "@set mysql_version " > $@
+ grep "AM_INIT_AUTOMAKE(mysql, " ../configure.in | \
+ sed -e 's;AM_INIT_AUTOMAKE(mysql, ;;' -e 's;);;' >> $@
+ echo -n "@set default_port " >> $@
+ grep "MYSQL_TCP_PORT_DEFAULT=" ../configure.in | \
+ sed -e 's;MYSQL_TCP_PORT_DEFAULT=;;' >> $@
+
+mysql.info: manual.texi include.texi
+ cd $(srcdir) && $(MAKEINFO) --no-split -I $(srcdir) $<
+
+manual.txt: manual.texi include.texi
+ cd $(srcdir) && \
+ $(MAKEINFO) -I $(srcdir) --no-headers --no-split --output $@ $<
+
+manual.html: manual.texi include.texi $(srcdir)/Support/texi2html
+ cd $(srcdir) && @PERL@ $(srcdir)/Support/texi2html $(TEXI2HTML_FLAGS) $<
+
+# Fix: add --output-comment with some interesting info?
+# Fix: @image worked with a older version of pdftex.
+# Comment: We need to run pdftex 2 times to get the cross references right.
+manual.pdf: manual.texi
+ cat manual.texi | sed -e 's|@image{[^}]*} *||g' > manual-tmp.texi; \
+ pdftex --interaction=nonstopmode '\input manual-tmp.texi'; \
+ pdftex --interaction=nonstopmode '\pdfcompresslevel=9' \
+ '\input manual-tmp.texi'; \
+ mv manual-tmp.pdf manual.pdf; \
+ rm -f manual-tmp.* ; \
+ touch $@
+
+# The texi2dvi gives a lot of harmless errors. Just ignore them unless
+# you want to help with the typesetting part.
+# This is the European papersize version
+manual_a4.ps: manual.texi include.texi
+ TEXINPUTS=$(srcdir):$$TEXINPUTS \
+ MAKEINFO='$(MAKEINFO) -I $(srcdir)' \
+ $(TEXI2DVI) --batch --texinfo '@afourpaper' $<
+ $(DVIPS) -t a4 manual.dvi -o $@
+ touch $@
+
+# This is the American papersize version
+manual_letter.ps: manual.texi include.texi
+ TEXINPUTS=$(srcdir):$$TEXINPUTS \
+ MAKEINFO='$(MAKEINFO) -I $(srcdir)' \
+ $(TEXI2DVI) --batch $<
+ $(DVIPS) -t letter manual.dvi -o $@
+ touch $@
+
+# Include images for the manual in the distribution
+dist-hook:
+ BD=`cd $(top_srcdir); pwd`; \
+ if test ! -d $(distdir)/Flags; then mkdir -p $(distdir)/Flags; fi; \
+ cp -p $(srcdir)/Flags/*.gif $(srcdir)/Flags/*.eps $(srcdir)/Flags/*.txt \
+ $(distdir)/Flags;
+ echo "PostScript and PDF versions suitable for printing" \
+ > $(distdir)/manual.ps
+ echo "are available from http://www.mysql.com/Manual/" \
+ >> $(distdir)/manual.ps
+ echo "or any mirror site" \
+ >> $(distdir)/manual.ps
+
+GT = $(srcdir)/Support/generate-text-files.pl
+
+../INSTALL-SOURCE: mysql.info $(GT)
+ perl -w $(GT) mysql.info "Installing" "Compatibility" > $@
+
+# We put the description for the binary installation here so that
+# people who download source wont have to see it. It is moved up to
+# the toplevel by the script that makes the binary tar files.
+INSTALL-BINARY: mysql.info $(GT)
+ perl -w $(GT) mysql.info "Installing binary" "Installing source" > $@
+
+../COPYING: mysql.info $(GT)
+ perl -w $(GT) mysql.info "GPL license" "LGPL license" > $@
+
+../COPYING.LIB: mysql.info $(GT)
+ perl -w $(GT) mysql.info "LGPL license" "Function Index" > $@
+
+../MIRRORS: manual.texi $(srcdir)/Support/generate-mirror-listing.pl
+ perl -w $(srcdir)/Support/generate-mirror-listing.pl manual.texi > $@
diff --git a/Docs/MySQL-logos/mysql-01.gif b/Docs/MySQL-logos/mysql-01.gif
new file mode 100644
index 00000000000..773453f8dd7
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-01.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-02.gif b/Docs/MySQL-logos/mysql-02.gif
new file mode 100644
index 00000000000..12d984b55e0
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-02.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-03.gif b/Docs/MySQL-logos/mysql-03.gif
new file mode 100644
index 00000000000..abb16f2aa59
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-03.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-04.gif b/Docs/MySQL-logos/mysql-04.gif
new file mode 100644
index 00000000000..e207e1790f7
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-04.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-05.gif b/Docs/MySQL-logos/mysql-05.gif
new file mode 100644
index 00000000000..f78b8a17b93
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-05.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-06.gif b/Docs/MySQL-logos/mysql-06.gif
new file mode 100644
index 00000000000..c660e1d1f4f
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-06.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-07.gif b/Docs/MySQL-logos/mysql-07.gif
new file mode 100644
index 00000000000..be309d0de1c
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-07.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-08.gif b/Docs/MySQL-logos/mysql-08.gif
new file mode 100644
index 00000000000..3d5b2135655
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-08.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-09.gif b/Docs/MySQL-logos/mysql-09.gif
new file mode 100644
index 00000000000..75d08592795
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-09.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-10.gif b/Docs/MySQL-logos/mysql-10.gif
new file mode 100644
index 00000000000..8d0a8551e9e
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-10.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-11.gif b/Docs/MySQL-logos/mysql-11.gif
new file mode 100644
index 00000000000..e5f3770a7bd
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-11.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-12.gif b/Docs/MySQL-logos/mysql-12.gif
new file mode 100644
index 00000000000..b045aaf3549
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-12.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-13.gif b/Docs/MySQL-logos/mysql-13.gif
new file mode 100644
index 00000000000..0d5aaf88f6f
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-13.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-14.gif b/Docs/MySQL-logos/mysql-14.gif
new file mode 100644
index 00000000000..9bce287b4b3
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-14.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-15.gif b/Docs/MySQL-logos/mysql-15.gif
new file mode 100644
index 00000000000..d70ffec83dd
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-15.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-16.gif b/Docs/MySQL-logos/mysql-16.gif
new file mode 100644
index 00000000000..9b30833dc1d
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-16.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-17.gif b/Docs/MySQL-logos/mysql-17.gif
new file mode 100644
index 00000000000..5b228496b66
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-17.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql-compatible.jpg b/Docs/MySQL-logos/mysql-compatible.jpg
new file mode 100644
index 00000000000..cce9cf84b91
--- /dev/null
+++ b/Docs/MySQL-logos/mysql-compatible.jpg
Binary files differ
diff --git a/Docs/MySQL-logos/mysql_anim-01.gif b/Docs/MySQL-logos/mysql_anim-01.gif
new file mode 100644
index 00000000000..f537d60da41
--- /dev/null
+++ b/Docs/MySQL-logos/mysql_anim-01.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql_anim-02.gif b/Docs/MySQL-logos/mysql_anim-02.gif
new file mode 100644
index 00000000000..cfd3e1cfc3e
--- /dev/null
+++ b/Docs/MySQL-logos/mysql_anim-02.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql_anim-03.gif b/Docs/MySQL-logos/mysql_anim-03.gif
new file mode 100644
index 00000000000..6ac6b3ebcc1
--- /dev/null
+++ b/Docs/MySQL-logos/mysql_anim-03.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql_anim-04.gif b/Docs/MySQL-logos/mysql_anim-04.gif
new file mode 100644
index 00000000000..d3150860ecf
--- /dev/null
+++ b/Docs/MySQL-logos/mysql_anim-04.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql_anim-05.gif b/Docs/MySQL-logos/mysql_anim-05.gif
new file mode 100644
index 00000000000..46f288ef71d
--- /dev/null
+++ b/Docs/MySQL-logos/mysql_anim-05.gif
Binary files differ
diff --git a/Docs/MySQL-logos/mysql_anim-06.gif b/Docs/MySQL-logos/mysql_anim-06.gif
new file mode 100644
index 00000000000..3dc283dbfb6
--- /dev/null
+++ b/Docs/MySQL-logos/mysql_anim-06.gif
Binary files differ
diff --git a/Docs/Raw-Flags/afghanistan.gif b/Docs/Raw-Flags/afghanistan.gif
new file mode 100644
index 00000000000..2cd2b54d8f5
--- /dev/null
+++ b/Docs/Raw-Flags/afghanistan.gif
Binary files differ
diff --git a/Docs/Raw-Flags/albania.gif b/Docs/Raw-Flags/albania.gif
new file mode 100644
index 00000000000..d5c8e0c4251
--- /dev/null
+++ b/Docs/Raw-Flags/albania.gif
Binary files differ
diff --git a/Docs/Raw-Flags/algeria.gif b/Docs/Raw-Flags/algeria.gif
new file mode 100644
index 00000000000..db8e4a4f52f
--- /dev/null
+++ b/Docs/Raw-Flags/algeria.gif
Binary files differ
diff --git a/Docs/Raw-Flags/andorra.gif b/Docs/Raw-Flags/andorra.gif
new file mode 100644
index 00000000000..4191a68ed4c
--- /dev/null
+++ b/Docs/Raw-Flags/andorra.gif
Binary files differ
diff --git a/Docs/Raw-Flags/angola.gif b/Docs/Raw-Flags/angola.gif
new file mode 100644
index 00000000000..40cce332a4e
--- /dev/null
+++ b/Docs/Raw-Flags/angola.gif
Binary files differ
diff --git a/Docs/Raw-Flags/antartica.gif b/Docs/Raw-Flags/antartica.gif
new file mode 100644
index 00000000000..3f7eac3f31c
--- /dev/null
+++ b/Docs/Raw-Flags/antartica.gif
Binary files differ
diff --git a/Docs/Raw-Flags/antigua-and-barbuda.gif b/Docs/Raw-Flags/antigua-and-barbuda.gif
new file mode 100644
index 00000000000..8cdc6e9f69c
--- /dev/null
+++ b/Docs/Raw-Flags/antigua-and-barbuda.gif
Binary files differ
diff --git a/Docs/Raw-Flags/argentina.gif b/Docs/Raw-Flags/argentina.gif
new file mode 100644
index 00000000000..dce5943f382
--- /dev/null
+++ b/Docs/Raw-Flags/argentina.gif
Binary files differ
diff --git a/Docs/Raw-Flags/armenia.gif b/Docs/Raw-Flags/armenia.gif
new file mode 100644
index 00000000000..c59294998cf
--- /dev/null
+++ b/Docs/Raw-Flags/armenia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/australia.gif b/Docs/Raw-Flags/australia.gif
new file mode 100644
index 00000000000..0a7174bc277
--- /dev/null
+++ b/Docs/Raw-Flags/australia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/austria.gif b/Docs/Raw-Flags/austria.gif
new file mode 100644
index 00000000000..c4f251ccae3
--- /dev/null
+++ b/Docs/Raw-Flags/austria.gif
Binary files differ
diff --git a/Docs/Raw-Flags/azerbaijan.gif b/Docs/Raw-Flags/azerbaijan.gif
new file mode 100644
index 00000000000..455a21682a2
--- /dev/null
+++ b/Docs/Raw-Flags/azerbaijan.gif
Binary files differ
diff --git a/Docs/Raw-Flags/bahamas.gif b/Docs/Raw-Flags/bahamas.gif
new file mode 100644
index 00000000000..bdfcda7dcfc
--- /dev/null
+++ b/Docs/Raw-Flags/bahamas.gif
Binary files differ
diff --git a/Docs/Raw-Flags/bahrein.gif b/Docs/Raw-Flags/bahrein.gif
new file mode 100644
index 00000000000..3fa9f84a812
--- /dev/null
+++ b/Docs/Raw-Flags/bahrein.gif
Binary files differ
diff --git a/Docs/Raw-Flags/bangladesh.gif b/Docs/Raw-Flags/bangladesh.gif
new file mode 100644
index 00000000000..d16696cfdb2
--- /dev/null
+++ b/Docs/Raw-Flags/bangladesh.gif
Binary files differ
diff --git a/Docs/Raw-Flags/barbados.gif b/Docs/Raw-Flags/barbados.gif
new file mode 100644
index 00000000000..6370aff79ba
--- /dev/null
+++ b/Docs/Raw-Flags/barbados.gif
Binary files differ
diff --git a/Docs/Raw-Flags/belarus.gif b/Docs/Raw-Flags/belarus.gif
new file mode 100644
index 00000000000..68498ad61e8
--- /dev/null
+++ b/Docs/Raw-Flags/belarus.gif
Binary files differ
diff --git a/Docs/Raw-Flags/belgium.gif b/Docs/Raw-Flags/belgium.gif
new file mode 100644
index 00000000000..6822fd4d923
--- /dev/null
+++ b/Docs/Raw-Flags/belgium.gif
Binary files differ
diff --git a/Docs/Raw-Flags/belize.gif b/Docs/Raw-Flags/belize.gif
new file mode 100644
index 00000000000..9665a50b0ae
--- /dev/null
+++ b/Docs/Raw-Flags/belize.gif
Binary files differ
diff --git a/Docs/Raw-Flags/benin.gif b/Docs/Raw-Flags/benin.gif
new file mode 100644
index 00000000000..3b29c8a1210
--- /dev/null
+++ b/Docs/Raw-Flags/benin.gif
Binary files differ
diff --git a/Docs/Raw-Flags/bermuda.gif b/Docs/Raw-Flags/bermuda.gif
new file mode 100644
index 00000000000..e46e200e6ea
--- /dev/null
+++ b/Docs/Raw-Flags/bermuda.gif
Binary files differ
diff --git a/Docs/Raw-Flags/bhutan.gif b/Docs/Raw-Flags/bhutan.gif
new file mode 100644
index 00000000000..52ed6ad162e
--- /dev/null
+++ b/Docs/Raw-Flags/bhutan.gif
Binary files differ
diff --git a/Docs/Raw-Flags/bolivia.gif b/Docs/Raw-Flags/bolivia.gif
new file mode 100644
index 00000000000..8b2491294a9
--- /dev/null
+++ b/Docs/Raw-Flags/bolivia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/bosnia-and-herzegovina.gif b/Docs/Raw-Flags/bosnia-and-herzegovina.gif
new file mode 100644
index 00000000000..c01717206ef
--- /dev/null
+++ b/Docs/Raw-Flags/bosnia-and-herzegovina.gif
Binary files differ
diff --git a/Docs/Raw-Flags/botswana.gif b/Docs/Raw-Flags/botswana.gif
new file mode 100644
index 00000000000..7ffc9b76f36
--- /dev/null
+++ b/Docs/Raw-Flags/botswana.gif
Binary files differ
diff --git a/Docs/Raw-Flags/brazil.gif b/Docs/Raw-Flags/brazil.gif
new file mode 100644
index 00000000000..92a2fe82ef1
--- /dev/null
+++ b/Docs/Raw-Flags/brazil.gif
Binary files differ
diff --git a/Docs/Raw-Flags/brunei.gif b/Docs/Raw-Flags/brunei.gif
new file mode 100644
index 00000000000..d64d5c381a0
--- /dev/null
+++ b/Docs/Raw-Flags/brunei.gif
Binary files differ
diff --git a/Docs/Raw-Flags/bulgaria.gif b/Docs/Raw-Flags/bulgaria.gif
new file mode 100644
index 00000000000..7df52d126b5
--- /dev/null
+++ b/Docs/Raw-Flags/bulgaria.gif
Binary files differ
diff --git a/Docs/Raw-Flags/burkina-faso.gif b/Docs/Raw-Flags/burkina-faso.gif
new file mode 100644
index 00000000000..803e1d6e9c1
--- /dev/null
+++ b/Docs/Raw-Flags/burkina-faso.gif
Binary files differ
diff --git a/Docs/Raw-Flags/burma.gif b/Docs/Raw-Flags/burma.gif
new file mode 100644
index 00000000000..44d63cc1e18
--- /dev/null
+++ b/Docs/Raw-Flags/burma.gif
Binary files differ
diff --git a/Docs/Raw-Flags/burundi.gif b/Docs/Raw-Flags/burundi.gif
new file mode 100644
index 00000000000..dee8e5ef7cd
--- /dev/null
+++ b/Docs/Raw-Flags/burundi.gif
Binary files differ
diff --git a/Docs/Raw-Flags/cambodia.gif b/Docs/Raw-Flags/cambodia.gif
new file mode 100644
index 00000000000..95314128b2c
--- /dev/null
+++ b/Docs/Raw-Flags/cambodia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/cameroon.gif b/Docs/Raw-Flags/cameroon.gif
new file mode 100644
index 00000000000..5fcd73b81d3
--- /dev/null
+++ b/Docs/Raw-Flags/cameroon.gif
Binary files differ
diff --git a/Docs/Raw-Flags/canada.gif b/Docs/Raw-Flags/canada.gif
new file mode 100644
index 00000000000..e4aafab3ec2
--- /dev/null
+++ b/Docs/Raw-Flags/canada.gif
Binary files differ
diff --git a/Docs/Raw-Flags/cape-verde.gif b/Docs/Raw-Flags/cape-verde.gif
new file mode 100644
index 00000000000..dc2712c4e12
--- /dev/null
+++ b/Docs/Raw-Flags/cape-verde.gif
Binary files differ
diff --git a/Docs/Raw-Flags/central-african-republic.gif b/Docs/Raw-Flags/central-african-republic.gif
new file mode 100644
index 00000000000..8bd1dc3d15f
--- /dev/null
+++ b/Docs/Raw-Flags/central-african-republic.gif
Binary files differ
diff --git a/Docs/Raw-Flags/chad.gif b/Docs/Raw-Flags/chad.gif
new file mode 100644
index 00000000000..6dace6197af
--- /dev/null
+++ b/Docs/Raw-Flags/chad.gif
Binary files differ
diff --git a/Docs/Raw-Flags/chile.gif b/Docs/Raw-Flags/chile.gif
new file mode 100644
index 00000000000..30b16b6f335
--- /dev/null
+++ b/Docs/Raw-Flags/chile.gif
Binary files differ
diff --git a/Docs/Raw-Flags/china.gif b/Docs/Raw-Flags/china.gif
new file mode 100644
index 00000000000..211ebf52d3c
--- /dev/null
+++ b/Docs/Raw-Flags/china.gif
Binary files differ
diff --git a/Docs/Raw-Flags/colombia.gif b/Docs/Raw-Flags/colombia.gif
new file mode 100644
index 00000000000..f6f790c1b88
--- /dev/null
+++ b/Docs/Raw-Flags/colombia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/comoros.gif b/Docs/Raw-Flags/comoros.gif
new file mode 100644
index 00000000000..13f8da6111e
--- /dev/null
+++ b/Docs/Raw-Flags/comoros.gif
Binary files differ
diff --git a/Docs/Raw-Flags/congo.gif b/Docs/Raw-Flags/congo.gif
new file mode 100644
index 00000000000..2d485dcca6d
--- /dev/null
+++ b/Docs/Raw-Flags/congo.gif
Binary files differ
diff --git a/Docs/Raw-Flags/costa-rica.gif b/Docs/Raw-Flags/costa-rica.gif
new file mode 100644
index 00000000000..d52b6dddb1b
--- /dev/null
+++ b/Docs/Raw-Flags/costa-rica.gif
Binary files differ
diff --git a/Docs/Raw-Flags/cote-d-ivoire.gif b/Docs/Raw-Flags/cote-d-ivoire.gif
new file mode 100644
index 00000000000..e7323be021f
--- /dev/null
+++ b/Docs/Raw-Flags/cote-d-ivoire.gif
Binary files differ
diff --git a/Docs/Raw-Flags/croatia.gif b/Docs/Raw-Flags/croatia.gif
new file mode 100644
index 00000000000..25c69200761
--- /dev/null
+++ b/Docs/Raw-Flags/croatia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/cuba.gif b/Docs/Raw-Flags/cuba.gif
new file mode 100644
index 00000000000..0e2b6164b96
--- /dev/null
+++ b/Docs/Raw-Flags/cuba.gif
Binary files differ
diff --git a/Docs/Raw-Flags/cyprus.gif b/Docs/Raw-Flags/cyprus.gif
new file mode 100644
index 00000000000..7ee3602d91d
--- /dev/null
+++ b/Docs/Raw-Flags/cyprus.gif
Binary files differ
diff --git a/Docs/Raw-Flags/czech-republic.gif b/Docs/Raw-Flags/czech-republic.gif
new file mode 100644
index 00000000000..e99651120bb
--- /dev/null
+++ b/Docs/Raw-Flags/czech-republic.gif
Binary files differ
diff --git a/Docs/Raw-Flags/denmark-original-incorrect.gif b/Docs/Raw-Flags/denmark-original-incorrect.gif
new file mode 100644
index 00000000000..e1be8f21764
--- /dev/null
+++ b/Docs/Raw-Flags/denmark-original-incorrect.gif
Binary files differ
diff --git a/Docs/Raw-Flags/denmark.gif b/Docs/Raw-Flags/denmark.gif
new file mode 100644
index 00000000000..336f9a2f39f
--- /dev/null
+++ b/Docs/Raw-Flags/denmark.gif
Binary files differ
diff --git a/Docs/Raw-Flags/djibouti.gif b/Docs/Raw-Flags/djibouti.gif
new file mode 100644
index 00000000000..c30c7b47822
--- /dev/null
+++ b/Docs/Raw-Flags/djibouti.gif
Binary files differ
diff --git a/Docs/Raw-Flags/dominica.gif b/Docs/Raw-Flags/dominica.gif
new file mode 100644
index 00000000000..ae69b33be58
--- /dev/null
+++ b/Docs/Raw-Flags/dominica.gif
Binary files differ
diff --git a/Docs/Raw-Flags/dominican-republic.gif b/Docs/Raw-Flags/dominican-republic.gif
new file mode 100644
index 00000000000..e2620c5b50f
--- /dev/null
+++ b/Docs/Raw-Flags/dominican-republic.gif
Binary files differ
diff --git a/Docs/Raw-Flags/ecuador.gif b/Docs/Raw-Flags/ecuador.gif
new file mode 100644
index 00000000000..ff94fc4a173
--- /dev/null
+++ b/Docs/Raw-Flags/ecuador.gif
Binary files differ
diff --git a/Docs/Raw-Flags/egypt.gif b/Docs/Raw-Flags/egypt.gif
new file mode 100644
index 00000000000..ba6a51e67bf
--- /dev/null
+++ b/Docs/Raw-Flags/egypt.gif
Binary files differ
diff --git a/Docs/Raw-Flags/el-salvador.gif b/Docs/Raw-Flags/el-salvador.gif
new file mode 100644
index 00000000000..602af34927b
--- /dev/null
+++ b/Docs/Raw-Flags/el-salvador.gif
Binary files differ
diff --git a/Docs/Raw-Flags/equatorial-guinea.gif b/Docs/Raw-Flags/equatorial-guinea.gif
new file mode 100644
index 00000000000..c35e9e613d0
--- /dev/null
+++ b/Docs/Raw-Flags/equatorial-guinea.gif
Binary files differ
diff --git a/Docs/Raw-Flags/eritrea.gif b/Docs/Raw-Flags/eritrea.gif
new file mode 100644
index 00000000000..127a185547a
--- /dev/null
+++ b/Docs/Raw-Flags/eritrea.gif
Binary files differ
diff --git a/Docs/Raw-Flags/estonia.gif b/Docs/Raw-Flags/estonia.gif
new file mode 100644
index 00000000000..3462f84c4df
--- /dev/null
+++ b/Docs/Raw-Flags/estonia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/ethiopia.gif b/Docs/Raw-Flags/ethiopia.gif
new file mode 100644
index 00000000000..5f3611ed09e
--- /dev/null
+++ b/Docs/Raw-Flags/ethiopia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/fiji.gif b/Docs/Raw-Flags/fiji.gif
new file mode 100644
index 00000000000..b20bbd3d467
--- /dev/null
+++ b/Docs/Raw-Flags/fiji.gif
Binary files differ
diff --git a/Docs/Raw-Flags/finland.gif b/Docs/Raw-Flags/finland.gif
new file mode 100644
index 00000000000..b923a5b6850
--- /dev/null
+++ b/Docs/Raw-Flags/finland.gif
Binary files differ
diff --git a/Docs/Raw-Flags/france.gif b/Docs/Raw-Flags/france.gif
new file mode 100644
index 00000000000..3f34a4feada
--- /dev/null
+++ b/Docs/Raw-Flags/france.gif
Binary files differ
diff --git a/Docs/Raw-Flags/gabon.gif b/Docs/Raw-Flags/gabon.gif
new file mode 100644
index 00000000000..ec10b2ee0b0
--- /dev/null
+++ b/Docs/Raw-Flags/gabon.gif
Binary files differ
diff --git a/Docs/Raw-Flags/gambia.gif b/Docs/Raw-Flags/gambia.gif
new file mode 100644
index 00000000000..590a4242fdc
--- /dev/null
+++ b/Docs/Raw-Flags/gambia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/georgia.gif b/Docs/Raw-Flags/georgia.gif
new file mode 100644
index 00000000000..ffa94298ec8
--- /dev/null
+++ b/Docs/Raw-Flags/georgia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/germany.gif b/Docs/Raw-Flags/germany.gif
new file mode 100644
index 00000000000..4045cd0fa29
--- /dev/null
+++ b/Docs/Raw-Flags/germany.gif
Binary files differ
diff --git a/Docs/Raw-Flags/ghana.gif b/Docs/Raw-Flags/ghana.gif
new file mode 100644
index 00000000000..f87596c1a19
--- /dev/null
+++ b/Docs/Raw-Flags/ghana.gif
Binary files differ
diff --git a/Docs/Raw-Flags/great-britain.gif b/Docs/Raw-Flags/great-britain.gif
new file mode 100644
index 00000000000..093d611c60c
--- /dev/null
+++ b/Docs/Raw-Flags/great-britain.gif
Binary files differ
diff --git a/Docs/Raw-Flags/greece.gif b/Docs/Raw-Flags/greece.gif
new file mode 100644
index 00000000000..26b0b18a28f
--- /dev/null
+++ b/Docs/Raw-Flags/greece.gif
Binary files differ
diff --git a/Docs/Raw-Flags/greenland.gif b/Docs/Raw-Flags/greenland.gif
new file mode 100644
index 00000000000..3885b7c8352
--- /dev/null
+++ b/Docs/Raw-Flags/greenland.gif
Binary files differ
diff --git a/Docs/Raw-Flags/grenada.gif b/Docs/Raw-Flags/grenada.gif
new file mode 100644
index 00000000000..f429051f7eb
--- /dev/null
+++ b/Docs/Raw-Flags/grenada.gif
Binary files differ
diff --git a/Docs/Raw-Flags/guatemala.gif b/Docs/Raw-Flags/guatemala.gif
new file mode 100644
index 00000000000..6d3684ed31b
--- /dev/null
+++ b/Docs/Raw-Flags/guatemala.gif
Binary files differ
diff --git a/Docs/Raw-Flags/guinea-bissau.gif b/Docs/Raw-Flags/guinea-bissau.gif
new file mode 100644
index 00000000000..adcabbda0ab
--- /dev/null
+++ b/Docs/Raw-Flags/guinea-bissau.gif
Binary files differ
diff --git a/Docs/Raw-Flags/guinea.gif b/Docs/Raw-Flags/guinea.gif
new file mode 100644
index 00000000000..ecc584d2e3b
--- /dev/null
+++ b/Docs/Raw-Flags/guinea.gif
Binary files differ
diff --git a/Docs/Raw-Flags/guyana.gif b/Docs/Raw-Flags/guyana.gif
new file mode 100644
index 00000000000..55385b9a3f5
--- /dev/null
+++ b/Docs/Raw-Flags/guyana.gif
Binary files differ
diff --git a/Docs/Raw-Flags/haiti.gif b/Docs/Raw-Flags/haiti.gif
new file mode 100644
index 00000000000..fe6cdee72bb
--- /dev/null
+++ b/Docs/Raw-Flags/haiti.gif
Binary files differ
diff --git a/Docs/Raw-Flags/honduras.gif b/Docs/Raw-Flags/honduras.gif
new file mode 100644
index 00000000000..1136e352d91
--- /dev/null
+++ b/Docs/Raw-Flags/honduras.gif
Binary files differ
diff --git a/Docs/Raw-Flags/hungary.gif b/Docs/Raw-Flags/hungary.gif
new file mode 100644
index 00000000000..48e1741d8ea
--- /dev/null
+++ b/Docs/Raw-Flags/hungary.gif
Binary files differ
diff --git a/Docs/Raw-Flags/iceland.gif b/Docs/Raw-Flags/iceland.gif
new file mode 100644
index 00000000000..9ba19690ea3
--- /dev/null
+++ b/Docs/Raw-Flags/iceland.gif
Binary files differ
diff --git a/Docs/Raw-Flags/india.gif b/Docs/Raw-Flags/india.gif
new file mode 100644
index 00000000000..5e51de863f5
--- /dev/null
+++ b/Docs/Raw-Flags/india.gif
Binary files differ
diff --git a/Docs/Raw-Flags/indonesia.gif b/Docs/Raw-Flags/indonesia.gif
new file mode 100644
index 00000000000..bf6bec293c7
--- /dev/null
+++ b/Docs/Raw-Flags/indonesia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/iran.gif b/Docs/Raw-Flags/iran.gif
new file mode 100644
index 00000000000..cdab0112459
--- /dev/null
+++ b/Docs/Raw-Flags/iran.gif
Binary files differ
diff --git a/Docs/Raw-Flags/iraq.gif b/Docs/Raw-Flags/iraq.gif
new file mode 100644
index 00000000000..2437eec12f8
--- /dev/null
+++ b/Docs/Raw-Flags/iraq.gif
Binary files differ
diff --git a/Docs/Raw-Flags/ireland.gif b/Docs/Raw-Flags/ireland.gif
new file mode 100644
index 00000000000..a69001e19a9
--- /dev/null
+++ b/Docs/Raw-Flags/ireland.gif
Binary files differ
diff --git a/Docs/Raw-Flags/israel.gif b/Docs/Raw-Flags/israel.gif
new file mode 100644
index 00000000000..e349db15526
--- /dev/null
+++ b/Docs/Raw-Flags/israel.gif
Binary files differ
diff --git a/Docs/Raw-Flags/italy.gif b/Docs/Raw-Flags/italy.gif
new file mode 100644
index 00000000000..8b2a67c75ab
--- /dev/null
+++ b/Docs/Raw-Flags/italy.gif
Binary files differ
diff --git a/Docs/Raw-Flags/jamaica.gif b/Docs/Raw-Flags/jamaica.gif
new file mode 100644
index 00000000000..16e30216ba6
--- /dev/null
+++ b/Docs/Raw-Flags/jamaica.gif
Binary files differ
diff --git a/Docs/Raw-Flags/japan.gif b/Docs/Raw-Flags/japan.gif
new file mode 100644
index 00000000000..a4cbf7ac5ca
--- /dev/null
+++ b/Docs/Raw-Flags/japan.gif
Binary files differ
diff --git a/Docs/Raw-Flags/jordan.gif b/Docs/Raw-Flags/jordan.gif
new file mode 100644
index 00000000000..ca4d16c2d22
--- /dev/null
+++ b/Docs/Raw-Flags/jordan.gif
Binary files differ
diff --git a/Docs/Raw-Flags/kazakhstan.gif b/Docs/Raw-Flags/kazakhstan.gif
new file mode 100644
index 00000000000..b687186342f
--- /dev/null
+++ b/Docs/Raw-Flags/kazakhstan.gif
Binary files differ
diff --git a/Docs/Raw-Flags/kenya.gif b/Docs/Raw-Flags/kenya.gif
new file mode 100644
index 00000000000..2b4ff6e682b
--- /dev/null
+++ b/Docs/Raw-Flags/kenya.gif
Binary files differ
diff --git a/Docs/Raw-Flags/kiribati.gif b/Docs/Raw-Flags/kiribati.gif
new file mode 100644
index 00000000000..0e4ba3832d3
--- /dev/null
+++ b/Docs/Raw-Flags/kiribati.gif
Binary files differ
diff --git a/Docs/Raw-Flags/kuwait.gif b/Docs/Raw-Flags/kuwait.gif
new file mode 100644
index 00000000000..007664b6d68
--- /dev/null
+++ b/Docs/Raw-Flags/kuwait.gif
Binary files differ
diff --git a/Docs/Raw-Flags/kyrgyzstan.gif b/Docs/Raw-Flags/kyrgyzstan.gif
new file mode 100644
index 00000000000..0a22c27173f
--- /dev/null
+++ b/Docs/Raw-Flags/kyrgyzstan.gif
Binary files differ
diff --git a/Docs/Raw-Flags/laos.gif b/Docs/Raw-Flags/laos.gif
new file mode 100644
index 00000000000..f9f43106038
--- /dev/null
+++ b/Docs/Raw-Flags/laos.gif
Binary files differ
diff --git a/Docs/Raw-Flags/latvia.gif b/Docs/Raw-Flags/latvia.gif
new file mode 100644
index 00000000000..a364abdabaa
--- /dev/null
+++ b/Docs/Raw-Flags/latvia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/lebanon.gif b/Docs/Raw-Flags/lebanon.gif
new file mode 100644
index 00000000000..524b6c60b1c
--- /dev/null
+++ b/Docs/Raw-Flags/lebanon.gif
Binary files differ
diff --git a/Docs/Raw-Flags/lesotho.gif b/Docs/Raw-Flags/lesotho.gif
new file mode 100644
index 00000000000..de242ec77d1
--- /dev/null
+++ b/Docs/Raw-Flags/lesotho.gif
Binary files differ
diff --git a/Docs/Raw-Flags/liberia.gif b/Docs/Raw-Flags/liberia.gif
new file mode 100644
index 00000000000..f1b908e5fa0
--- /dev/null
+++ b/Docs/Raw-Flags/liberia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/libya.gif b/Docs/Raw-Flags/libya.gif
new file mode 100644
index 00000000000..55a121435cc
--- /dev/null
+++ b/Docs/Raw-Flags/libya.gif
Binary files differ
diff --git a/Docs/Raw-Flags/liechtenstein.gif b/Docs/Raw-Flags/liechtenstein.gif
new file mode 100644
index 00000000000..fe24e828b0b
--- /dev/null
+++ b/Docs/Raw-Flags/liechtenstein.gif
Binary files differ
diff --git a/Docs/Raw-Flags/lithuania.gif b/Docs/Raw-Flags/lithuania.gif
new file mode 100644
index 00000000000..849d0a17d9a
--- /dev/null
+++ b/Docs/Raw-Flags/lithuania.gif
Binary files differ
diff --git a/Docs/Raw-Flags/luxembourg.gif b/Docs/Raw-Flags/luxembourg.gif
new file mode 100644
index 00000000000..9ec9d31a439
--- /dev/null
+++ b/Docs/Raw-Flags/luxembourg.gif
Binary files differ
diff --git a/Docs/Raw-Flags/macedonia.gif b/Docs/Raw-Flags/macedonia.gif
new file mode 100644
index 00000000000..174506e0021
--- /dev/null
+++ b/Docs/Raw-Flags/macedonia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/madagascar.gif b/Docs/Raw-Flags/madagascar.gif
new file mode 100644
index 00000000000..18db5d26ff5
--- /dev/null
+++ b/Docs/Raw-Flags/madagascar.gif
Binary files differ
diff --git a/Docs/Raw-Flags/malawi.gif b/Docs/Raw-Flags/malawi.gif
new file mode 100644
index 00000000000..76ffcf0585d
--- /dev/null
+++ b/Docs/Raw-Flags/malawi.gif
Binary files differ
diff --git a/Docs/Raw-Flags/malaysia.gif b/Docs/Raw-Flags/malaysia.gif
new file mode 100644
index 00000000000..d29656ebefe
--- /dev/null
+++ b/Docs/Raw-Flags/malaysia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/maldives.gif b/Docs/Raw-Flags/maldives.gif
new file mode 100644
index 00000000000..c0c53d9a868
--- /dev/null
+++ b/Docs/Raw-Flags/maldives.gif
Binary files differ
diff --git a/Docs/Raw-Flags/mali.gif b/Docs/Raw-Flags/mali.gif
new file mode 100644
index 00000000000..b2430b3de65
--- /dev/null
+++ b/Docs/Raw-Flags/mali.gif
Binary files differ
diff --git a/Docs/Raw-Flags/malta.gif b/Docs/Raw-Flags/malta.gif
new file mode 100644
index 00000000000..1db0ec66a8b
--- /dev/null
+++ b/Docs/Raw-Flags/malta.gif
Binary files differ
diff --git a/Docs/Raw-Flags/marshall.gif b/Docs/Raw-Flags/marshall.gif
new file mode 100644
index 00000000000..3574580b4da
--- /dev/null
+++ b/Docs/Raw-Flags/marshall.gif
Binary files differ
diff --git a/Docs/Raw-Flags/mauritania.gif b/Docs/Raw-Flags/mauritania.gif
new file mode 100644
index 00000000000..3cc19a06f7b
--- /dev/null
+++ b/Docs/Raw-Flags/mauritania.gif
Binary files differ
diff --git a/Docs/Raw-Flags/mauritius.gif b/Docs/Raw-Flags/mauritius.gif
new file mode 100644
index 00000000000..042083b74a7
--- /dev/null
+++ b/Docs/Raw-Flags/mauritius.gif
Binary files differ
diff --git a/Docs/Raw-Flags/mexico.gif b/Docs/Raw-Flags/mexico.gif
new file mode 100644
index 00000000000..978968cc2e3
--- /dev/null
+++ b/Docs/Raw-Flags/mexico.gif
Binary files differ
diff --git a/Docs/Raw-Flags/micronesia.gif b/Docs/Raw-Flags/micronesia.gif
new file mode 100644
index 00000000000..08ac921fbae
--- /dev/null
+++ b/Docs/Raw-Flags/micronesia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/moldova.gif b/Docs/Raw-Flags/moldova.gif
new file mode 100644
index 00000000000..553aaefa510
--- /dev/null
+++ b/Docs/Raw-Flags/moldova.gif
Binary files differ
diff --git a/Docs/Raw-Flags/monaco.gif b/Docs/Raw-Flags/monaco.gif
new file mode 100644
index 00000000000..bf6bec293c7
--- /dev/null
+++ b/Docs/Raw-Flags/monaco.gif
Binary files differ
diff --git a/Docs/Raw-Flags/mongolia.gif b/Docs/Raw-Flags/mongolia.gif
new file mode 100644
index 00000000000..b5031d9fba5
--- /dev/null
+++ b/Docs/Raw-Flags/mongolia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/morocco.gif b/Docs/Raw-Flags/morocco.gif
new file mode 100644
index 00000000000..3dbd19fc45a
--- /dev/null
+++ b/Docs/Raw-Flags/morocco.gif
Binary files differ
diff --git a/Docs/Raw-Flags/mozambique.gif b/Docs/Raw-Flags/mozambique.gif
new file mode 100644
index 00000000000..3bcafc6b40c
--- /dev/null
+++ b/Docs/Raw-Flags/mozambique.gif
Binary files differ
diff --git a/Docs/Raw-Flags/namibia.gif b/Docs/Raw-Flags/namibia.gif
new file mode 100644
index 00000000000..7d8ad5d8771
--- /dev/null
+++ b/Docs/Raw-Flags/namibia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/nauru.gif b/Docs/Raw-Flags/nauru.gif
new file mode 100644
index 00000000000..234ec7db143
--- /dev/null
+++ b/Docs/Raw-Flags/nauru.gif
Binary files differ
diff --git a/Docs/Raw-Flags/nepal.gif b/Docs/Raw-Flags/nepal.gif
new file mode 100644
index 00000000000..8d536ee4d3b
--- /dev/null
+++ b/Docs/Raw-Flags/nepal.gif
Binary files differ
diff --git a/Docs/Raw-Flags/netherlands.gif b/Docs/Raw-Flags/netherlands.gif
new file mode 100644
index 00000000000..8b170f1e0e8
--- /dev/null
+++ b/Docs/Raw-Flags/netherlands.gif
Binary files differ
diff --git a/Docs/Raw-Flags/new-zealand.gif b/Docs/Raw-Flags/new-zealand.gif
new file mode 100644
index 00000000000..4345c82e5be
--- /dev/null
+++ b/Docs/Raw-Flags/new-zealand.gif
Binary files differ
diff --git a/Docs/Raw-Flags/nicaragua.gif b/Docs/Raw-Flags/nicaragua.gif
new file mode 100644
index 00000000000..366ea5098f5
--- /dev/null
+++ b/Docs/Raw-Flags/nicaragua.gif
Binary files differ
diff --git a/Docs/Raw-Flags/niger.gif b/Docs/Raw-Flags/niger.gif
new file mode 100644
index 00000000000..d95591ec177
--- /dev/null
+++ b/Docs/Raw-Flags/niger.gif
Binary files differ
diff --git a/Docs/Raw-Flags/nigeria.gif b/Docs/Raw-Flags/nigeria.gif
new file mode 100644
index 00000000000..b80eeb0c4ab
--- /dev/null
+++ b/Docs/Raw-Flags/nigeria.gif
Binary files differ
diff --git a/Docs/Raw-Flags/north-korea.gif b/Docs/Raw-Flags/north-korea.gif
new file mode 100644
index 00000000000..83de4035423
--- /dev/null
+++ b/Docs/Raw-Flags/north-korea.gif
Binary files differ
diff --git a/Docs/Raw-Flags/norway.gif b/Docs/Raw-Flags/norway.gif
new file mode 100644
index 00000000000..936d41fb6c3
--- /dev/null
+++ b/Docs/Raw-Flags/norway.gif
Binary files differ
diff --git a/Docs/Raw-Flags/oman.gif b/Docs/Raw-Flags/oman.gif
new file mode 100644
index 00000000000..df611c57ad2
--- /dev/null
+++ b/Docs/Raw-Flags/oman.gif
Binary files differ
diff --git a/Docs/Raw-Flags/pakistan.gif b/Docs/Raw-Flags/pakistan.gif
new file mode 100644
index 00000000000..455846aad70
--- /dev/null
+++ b/Docs/Raw-Flags/pakistan.gif
Binary files differ
diff --git a/Docs/Raw-Flags/panama.gif b/Docs/Raw-Flags/panama.gif
new file mode 100644
index 00000000000..47dd1b70c85
--- /dev/null
+++ b/Docs/Raw-Flags/panama.gif
Binary files differ
diff --git a/Docs/Raw-Flags/papua-new-guinea.gif b/Docs/Raw-Flags/papua-new-guinea.gif
new file mode 100644
index 00000000000..a59c0d5a25d
--- /dev/null
+++ b/Docs/Raw-Flags/papua-new-guinea.gif
Binary files differ
diff --git a/Docs/Raw-Flags/paraguay.gif b/Docs/Raw-Flags/paraguay.gif
new file mode 100644
index 00000000000..8a9ba1b2688
--- /dev/null
+++ b/Docs/Raw-Flags/paraguay.gif
Binary files differ
diff --git a/Docs/Raw-Flags/peru.gif b/Docs/Raw-Flags/peru.gif
new file mode 100644
index 00000000000..d07cfc047df
--- /dev/null
+++ b/Docs/Raw-Flags/peru.gif
Binary files differ
diff --git a/Docs/Raw-Flags/philippines.gif b/Docs/Raw-Flags/philippines.gif
new file mode 100644
index 00000000000..9c2a2667c3c
--- /dev/null
+++ b/Docs/Raw-Flags/philippines.gif
Binary files differ
diff --git a/Docs/Raw-Flags/poland.gif b/Docs/Raw-Flags/poland.gif
new file mode 100644
index 00000000000..f6a26701ee9
--- /dev/null
+++ b/Docs/Raw-Flags/poland.gif
Binary files differ
diff --git a/Docs/Raw-Flags/portugal.gif b/Docs/Raw-Flags/portugal.gif
new file mode 100644
index 00000000000..59d8bc06d68
--- /dev/null
+++ b/Docs/Raw-Flags/portugal.gif
Binary files differ
diff --git a/Docs/Raw-Flags/qatar.gif b/Docs/Raw-Flags/qatar.gif
new file mode 100644
index 00000000000..a61a85f7e6a
--- /dev/null
+++ b/Docs/Raw-Flags/qatar.gif
Binary files differ
diff --git a/Docs/Raw-Flags/romania.gif b/Docs/Raw-Flags/romania.gif
new file mode 100644
index 00000000000..2214685caf0
--- /dev/null
+++ b/Docs/Raw-Flags/romania.gif
Binary files differ
diff --git a/Docs/Raw-Flags/russia.gif b/Docs/Raw-Flags/russia.gif
new file mode 100644
index 00000000000..3f52bd7d490
--- /dev/null
+++ b/Docs/Raw-Flags/russia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/rwanda.gif b/Docs/Raw-Flags/rwanda.gif
new file mode 100644
index 00000000000..71433f13b65
--- /dev/null
+++ b/Docs/Raw-Flags/rwanda.gif
Binary files differ
diff --git a/Docs/Raw-Flags/saint-kitts-and-nevis.gif b/Docs/Raw-Flags/saint-kitts-and-nevis.gif
new file mode 100644
index 00000000000..8036b6a1e5c
--- /dev/null
+++ b/Docs/Raw-Flags/saint-kitts-and-nevis.gif
Binary files differ
diff --git a/Docs/Raw-Flags/saint-lucia.gif b/Docs/Raw-Flags/saint-lucia.gif
new file mode 100644
index 00000000000..ff7043fe307
--- /dev/null
+++ b/Docs/Raw-Flags/saint-lucia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/samoa.gif b/Docs/Raw-Flags/samoa.gif
new file mode 100644
index 00000000000..08f135c84dc
--- /dev/null
+++ b/Docs/Raw-Flags/samoa.gif
Binary files differ
diff --git a/Docs/Raw-Flags/sao-tome-and-principe.gif b/Docs/Raw-Flags/sao-tome-and-principe.gif
new file mode 100644
index 00000000000..046c6d9155b
--- /dev/null
+++ b/Docs/Raw-Flags/sao-tome-and-principe.gif
Binary files differ
diff --git a/Docs/Raw-Flags/saudi-arabia.gif b/Docs/Raw-Flags/saudi-arabia.gif
new file mode 100644
index 00000000000..02838b2aa3d
--- /dev/null
+++ b/Docs/Raw-Flags/saudi-arabia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/senegal.gif b/Docs/Raw-Flags/senegal.gif
new file mode 100644
index 00000000000..e1de2967ce4
--- /dev/null
+++ b/Docs/Raw-Flags/senegal.gif
Binary files differ
diff --git a/Docs/Raw-Flags/seychelles.gif b/Docs/Raw-Flags/seychelles.gif
new file mode 100644
index 00000000000..3d647a269ee
--- /dev/null
+++ b/Docs/Raw-Flags/seychelles.gif
Binary files differ
diff --git a/Docs/Raw-Flags/sierra-leone.gif b/Docs/Raw-Flags/sierra-leone.gif
new file mode 100644
index 00000000000..41d5ca1c7eb
--- /dev/null
+++ b/Docs/Raw-Flags/sierra-leone.gif
Binary files differ
diff --git a/Docs/Raw-Flags/singapore.gif b/Docs/Raw-Flags/singapore.gif
new file mode 100644
index 00000000000..39e32de4179
--- /dev/null
+++ b/Docs/Raw-Flags/singapore.gif
Binary files differ
diff --git a/Docs/Raw-Flags/slovakia.gif b/Docs/Raw-Flags/slovakia.gif
new file mode 100644
index 00000000000..f997d1ca8e6
--- /dev/null
+++ b/Docs/Raw-Flags/slovakia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/slovenia.gif b/Docs/Raw-Flags/slovenia.gif
new file mode 100644
index 00000000000..05ff9f74b32
--- /dev/null
+++ b/Docs/Raw-Flags/slovenia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/solomon-islands.gif b/Docs/Raw-Flags/solomon-islands.gif
new file mode 100644
index 00000000000..7fe42e8cd8e
--- /dev/null
+++ b/Docs/Raw-Flags/solomon-islands.gif
Binary files differ
diff --git a/Docs/Raw-Flags/somalia.gif b/Docs/Raw-Flags/somalia.gif
new file mode 100644
index 00000000000..50876564aa8
--- /dev/null
+++ b/Docs/Raw-Flags/somalia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/south-africa.gif b/Docs/Raw-Flags/south-africa.gif
new file mode 100644
index 00000000000..48164f22111
--- /dev/null
+++ b/Docs/Raw-Flags/south-africa.gif
Binary files differ
diff --git a/Docs/Raw-Flags/south-korea.gif b/Docs/Raw-Flags/south-korea.gif
new file mode 100644
index 00000000000..7e79e557a77
--- /dev/null
+++ b/Docs/Raw-Flags/south-korea.gif
Binary files differ
diff --git a/Docs/Raw-Flags/spain.gif b/Docs/Raw-Flags/spain.gif
new file mode 100644
index 00000000000..cbf0734548f
--- /dev/null
+++ b/Docs/Raw-Flags/spain.gif
Binary files differ
diff --git a/Docs/Raw-Flags/sri-lanka.gif b/Docs/Raw-Flags/sri-lanka.gif
new file mode 100644
index 00000000000..05926227dfd
--- /dev/null
+++ b/Docs/Raw-Flags/sri-lanka.gif
Binary files differ
diff --git a/Docs/Raw-Flags/sudan.gif b/Docs/Raw-Flags/sudan.gif
new file mode 100644
index 00000000000..666c5d7b951
--- /dev/null
+++ b/Docs/Raw-Flags/sudan.gif
Binary files differ
diff --git a/Docs/Raw-Flags/suriname.gif b/Docs/Raw-Flags/suriname.gif
new file mode 100644
index 00000000000..7b156242944
--- /dev/null
+++ b/Docs/Raw-Flags/suriname.gif
Binary files differ
diff --git a/Docs/Raw-Flags/swaziland.gif b/Docs/Raw-Flags/swaziland.gif
new file mode 100644
index 00000000000..78a0628f44f
--- /dev/null
+++ b/Docs/Raw-Flags/swaziland.gif
Binary files differ
diff --git a/Docs/Raw-Flags/sweden.gif b/Docs/Raw-Flags/sweden.gif
new file mode 100644
index 00000000000..e26546b7649
--- /dev/null
+++ b/Docs/Raw-Flags/sweden.gif
Binary files differ
diff --git a/Docs/Raw-Flags/sweden2.gif b/Docs/Raw-Flags/sweden2.gif
new file mode 100644
index 00000000000..999a2a68b88
--- /dev/null
+++ b/Docs/Raw-Flags/sweden2.gif
Binary files differ
diff --git a/Docs/Raw-Flags/switzerland.gif b/Docs/Raw-Flags/switzerland.gif
new file mode 100644
index 00000000000..4256c5a28d0
--- /dev/null
+++ b/Docs/Raw-Flags/switzerland.gif
Binary files differ
diff --git a/Docs/Raw-Flags/syria.gif b/Docs/Raw-Flags/syria.gif
new file mode 100644
index 00000000000..2dd2c0b9e8b
--- /dev/null
+++ b/Docs/Raw-Flags/syria.gif
Binary files differ
diff --git a/Docs/Raw-Flags/taiwan.gif b/Docs/Raw-Flags/taiwan.gif
new file mode 100644
index 00000000000..ab8f843d49c
--- /dev/null
+++ b/Docs/Raw-Flags/taiwan.gif
Binary files differ
diff --git a/Docs/Raw-Flags/tajikistan.gif b/Docs/Raw-Flags/tajikistan.gif
new file mode 100644
index 00000000000..e41305e5ade
--- /dev/null
+++ b/Docs/Raw-Flags/tajikistan.gif
Binary files differ
diff --git a/Docs/Raw-Flags/tanzania.gif b/Docs/Raw-Flags/tanzania.gif
new file mode 100644
index 00000000000..b5e266a059a
--- /dev/null
+++ b/Docs/Raw-Flags/tanzania.gif
Binary files differ
diff --git a/Docs/Raw-Flags/thailand.gif b/Docs/Raw-Flags/thailand.gif
new file mode 100644
index 00000000000..68dde61999b
--- /dev/null
+++ b/Docs/Raw-Flags/thailand.gif
Binary files differ
diff --git a/Docs/Raw-Flags/togo.gif b/Docs/Raw-Flags/togo.gif
new file mode 100644
index 00000000000..fec51e649c8
--- /dev/null
+++ b/Docs/Raw-Flags/togo.gif
Binary files differ
diff --git a/Docs/Raw-Flags/tonga.gif b/Docs/Raw-Flags/tonga.gif
new file mode 100644
index 00000000000..e684b7b4a95
--- /dev/null
+++ b/Docs/Raw-Flags/tonga.gif
Binary files differ
diff --git a/Docs/Raw-Flags/trinidad-and-tobago.gif b/Docs/Raw-Flags/trinidad-and-tobago.gif
new file mode 100644
index 00000000000..73f6a90b3f8
--- /dev/null
+++ b/Docs/Raw-Flags/trinidad-and-tobago.gif
Binary files differ
diff --git a/Docs/Raw-Flags/tunisia.gif b/Docs/Raw-Flags/tunisia.gif
new file mode 100644
index 00000000000..4e9872ec826
--- /dev/null
+++ b/Docs/Raw-Flags/tunisia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/turkey.gif b/Docs/Raw-Flags/turkey.gif
new file mode 100644
index 00000000000..334fb57c703
--- /dev/null
+++ b/Docs/Raw-Flags/turkey.gif
Binary files differ
diff --git a/Docs/Raw-Flags/turkmenistan.gif b/Docs/Raw-Flags/turkmenistan.gif
new file mode 100644
index 00000000000..7b4af9ac158
--- /dev/null
+++ b/Docs/Raw-Flags/turkmenistan.gif
Binary files differ
diff --git a/Docs/Raw-Flags/tuvalu.gif b/Docs/Raw-Flags/tuvalu.gif
new file mode 100644
index 00000000000..0612803d157
--- /dev/null
+++ b/Docs/Raw-Flags/tuvalu.gif
Binary files differ
diff --git a/Docs/Raw-Flags/uganda.gif b/Docs/Raw-Flags/uganda.gif
new file mode 100644
index 00000000000..b2874526e53
--- /dev/null
+++ b/Docs/Raw-Flags/uganda.gif
Binary files differ
diff --git a/Docs/Raw-Flags/ukraine.gif b/Docs/Raw-Flags/ukraine.gif
new file mode 100644
index 00000000000..80abc1bb079
--- /dev/null
+++ b/Docs/Raw-Flags/ukraine.gif
Binary files differ
diff --git a/Docs/Raw-Flags/united-arab-emirates.gif b/Docs/Raw-Flags/united-arab-emirates.gif
new file mode 100644
index 00000000000..4d85bb0aeca
--- /dev/null
+++ b/Docs/Raw-Flags/united-arab-emirates.gif
Binary files differ
diff --git a/Docs/Raw-Flags/united-states-of-america.gif b/Docs/Raw-Flags/united-states-of-america.gif
new file mode 100644
index 00000000000..aaee9cef01f
--- /dev/null
+++ b/Docs/Raw-Flags/united-states-of-america.gif
Binary files differ
diff --git a/Docs/Raw-Flags/uruguay.gif b/Docs/Raw-Flags/uruguay.gif
new file mode 100644
index 00000000000..b772fcf47df
--- /dev/null
+++ b/Docs/Raw-Flags/uruguay.gif
Binary files differ
diff --git a/Docs/Raw-Flags/usa.gif b/Docs/Raw-Flags/usa.gif
new file mode 100644
index 00000000000..aaee9cef01f
--- /dev/null
+++ b/Docs/Raw-Flags/usa.gif
Binary files differ
diff --git a/Docs/Raw-Flags/uzbekistan.gif b/Docs/Raw-Flags/uzbekistan.gif
new file mode 100644
index 00000000000..27cfff2b4bb
--- /dev/null
+++ b/Docs/Raw-Flags/uzbekistan.gif
Binary files differ
diff --git a/Docs/Raw-Flags/vanuatu.gif b/Docs/Raw-Flags/vanuatu.gif
new file mode 100644
index 00000000000..936d22a1bee
--- /dev/null
+++ b/Docs/Raw-Flags/vanuatu.gif
Binary files differ
diff --git a/Docs/Raw-Flags/venezuela.gif b/Docs/Raw-Flags/venezuela.gif
new file mode 100644
index 00000000000..794f09cd856
--- /dev/null
+++ b/Docs/Raw-Flags/venezuela.gif
Binary files differ
diff --git a/Docs/Raw-Flags/vietnam.gif b/Docs/Raw-Flags/vietnam.gif
new file mode 100644
index 00000000000..0b9fc1add81
--- /dev/null
+++ b/Docs/Raw-Flags/vietnam.gif
Binary files differ
diff --git a/Docs/Raw-Flags/vincent-and-grenadines.gif b/Docs/Raw-Flags/vincent-and-grenadines.gif
new file mode 100644
index 00000000000..8a8689fbc39
--- /dev/null
+++ b/Docs/Raw-Flags/vincent-and-grenadines.gif
Binary files differ
diff --git a/Docs/Raw-Flags/yemen.gif b/Docs/Raw-Flags/yemen.gif
new file mode 100644
index 00000000000..f297f9fcef7
--- /dev/null
+++ b/Docs/Raw-Flags/yemen.gif
Binary files differ
diff --git a/Docs/Raw-Flags/yugoslavia.gif b/Docs/Raw-Flags/yugoslavia.gif
new file mode 100644
index 00000000000..ad7a1672692
--- /dev/null
+++ b/Docs/Raw-Flags/yugoslavia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/zaire.gif b/Docs/Raw-Flags/zaire.gif
new file mode 100644
index 00000000000..489320d32a9
--- /dev/null
+++ b/Docs/Raw-Flags/zaire.gif
Binary files differ
diff --git a/Docs/Raw-Flags/zambia.gif b/Docs/Raw-Flags/zambia.gif
new file mode 100644
index 00000000000..7cb18f157e3
--- /dev/null
+++ b/Docs/Raw-Flags/zambia.gif
Binary files differ
diff --git a/Docs/Raw-Flags/zimbabwe.gif b/Docs/Raw-Flags/zimbabwe.gif
new file mode 100644
index 00000000000..49d042fb265
--- /dev/null
+++ b/Docs/Raw-Flags/zimbabwe.gif
Binary files differ
diff --git a/Docs/Support/.cvsignore b/Docs/Support/.cvsignore
new file mode 100644
index 00000000000..8772614a6b6
--- /dev/null
+++ b/Docs/Support/.cvsignore
@@ -0,0 +1,2 @@
+manual.html
+manual_toc.html
diff --git a/Docs/Support/generate-flag-images b/Docs/Support/generate-flag-images
new file mode 100755
index 00000000000..fa31fa7a4b8
--- /dev/null
+++ b/Docs/Support/generate-flag-images
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+tmp=/tmp/temp-pic.pnm
+
+all="austria czech-republic germany great-britain hungary israel italy
+russia portugal sweden canada usa south-korea japan taiwan australia
+romania denmark france estonia poland singapore bulgaria south-africa
+netherlands chile ukraine greece finland switzerland croatia china
+brazil spain iceland ireland denmark"
+
+new=""
+
+set -x
+cd Img
+
+# for c in $all; do cp empty.png $c.pdf; done; exit
+
+for c in $new
+do
+ # For HTML version
+ giftopnm Raw-Flags/$c.gif | \
+ pnmscale -xsize 30 > $tmp
+ pnmpaste $tmp 1 1 flag-background.pnm > $c.pnm
+ rm -f $tmp
+ # For web version
+ ppmtogif $c.pnm > $c.gif
+ # or cjpeg -optimize -quality 70 -outfile $c.jpg
+ # For PDF version (this coredumps. use empty file until fixed)
+ # pnmtopng -verbose $c.pnm > $c.png
+ cp empty.png $c.pdf
+ # For TeX version
+ giftopnm /my/local/pictures/flags/$c.gif | \
+ pnmscale -xsize 30 | \
+ pnmtops -noturn > $c.eps
+ # For text version
+ echo -n "" > $c.txt
+done
diff --git a/Docs/Support/generate-mirror-listing.pl b/Docs/Support/generate-mirror-listing.pl
new file mode 100755
index 00000000000..1c6e579b330
--- /dev/null
+++ b/Docs/Support/generate-mirror-listing.pl
@@ -0,0 +1,27 @@
+#!/my/gnu/bin/perl -w -*- perl -*-
+
+# Generate a mirror listing
+
+line: while (<>) { last line if /START_OF_MIRROR_LISTING/;};
+
+print "MySQL mirror listing\n";
+
+line: while (<>)
+{
+ last line if /END_OF_MIRROR_LISTING/;
+ if (/^\@strong\{([A-Za-z ]+):\}$/)
+ {
+ print "\n*** $1\n";
+ }
+ elsif (m|^\@image\{Img/[a-z-]+\} ([A-Za-z]+) \[(.*)\]|)
+ {
+ print "\n$1 [$2]\n";
+ }
+ # A hacky URL regexp
+ # (m!^\@uref\{((http\|ftp)://[^,]*), (FTP\|WWW)\}!)
+ elsif (m!^\@uref\{((http|ftp)://[^,]*), (FTP|WWW)\}!)
+ {
+ $addr = $1;
+ print " $addr\n";
+ }
+}
diff --git a/Docs/Support/generate-text-files.pl b/Docs/Support/generate-text-files.pl
new file mode 100755
index 00000000000..570e579d926
--- /dev/null
+++ b/Docs/Support/generate-text-files.pl
@@ -0,0 +1,40 @@
+#!/my/gnu/bin/perl -w -*- perl -*-
+# Generate text files from top directory from the manual.
+
+$from = shift(@ARGV);
+$fnode = shift(@ARGV);
+$tnode = shift(@ARGV);
+
+open(IN, "$from") || die;
+
+$in = 0;
+
+while (<IN>)
+{
+ if ($in)
+ {
+ if (/Node: $tnode,/)
+ {
+ $in = 0;
+ }
+ elsif (/^File: mysql.info/ || (/^/))
+ {
+ # Just Skip node begginigs
+ }
+ else
+ {
+ print;
+ }
+ }
+ else
+ {
+ if (/Node: $fnode,/)
+ {
+ $in = 1;
+ # Skip first empty line
+ <IN>;
+ }
+ }
+}
+
+close(IN);
diff --git a/Docs/Support/make-makefile b/Docs/Support/make-makefile
new file mode 100755
index 00000000000..79cf06091fe
--- /dev/null
+++ b/Docs/Support/make-makefile
@@ -0,0 +1,7 @@
+#!/bin/sh
+# Use this when you have deleted Makefile and do not want to do a full
+# build to get it back
+
+cd ..
+automake --gnu Docs/Makefile
+CONFIG_FILES=Docs/Makefile CONFIG_HEADERS= sh ./config.status
diff --git a/Docs/Support/texi2html b/Docs/Support/texi2html
new file mode 100755
index 00000000000..fac665f3361
--- /dev/null
+++ b/Docs/Support/texi2html
@@ -0,0 +1,2251 @@
+#!PATH_TO_PERL -*- perl -*-
+# Add path to perl on the previous line and make this executable
+# if you want to use this as a normal script.
+'di ';
+'ig 00 ';
+#+##############################################################################
+# #
+# File: texi2html #
+# #
+# Description: Program to transform most Texinfo documents to HTML #
+# #
+#-##############################################################################
+
+# @(#)texi2html 1.52 971230 Written (mainly) by Lionel Cons, Lionel.Cons@cern.ch
+# Enhanced by David Axmark, david@detron.se
+
+# The man page for this program is included at the end of this file and can be
+# viewed using the command 'nroff -man texi2html'.
+# Please read the copyright at the end of the man page.
+
+#+++############################################################################
+# #
+# Constants #
+# #
+#---############################################################################
+
+$DEBUG_TOC = 1;
+$DEBUG_INDEX = 2;
+$DEBUG_BIB = 4;
+$DEBUG_GLOSS = 8;
+$DEBUG_DEF = 16;
+$DEBUG_HTML = 32;
+$DEBUG_USER = 64;
+
+$BIBRE = '\[[\w\/]+\]'; # RE for a bibliography reference
+$FILERE = '[\/\w.+-]+'; # RE for a file name
+$VARRE = '[^\s\{\}]+'; # RE for a variable name
+$NODERE = '[^@{}:\'`",]+'; # RE for a node name
+$NODESRE = '[^@{}:\'`"]+'; # RE for a list of node names
+$XREFRE = '[^@{}]+'; # RE for a xref (should use NODERE)
+
+$ERROR = "***"; # prefix for errors and warnings
+$THISPROG = "texi2html 1.52 (hacked by david\@detron.se)"; # program name and version
+$HOMEPAGE = "http://www.mathematik.uni-kl.de/~obachman/Texi2html/"; # program home page
+$TODAY = &pretty_date; # like "20 September 1993"
+$SPLITTAG = "<!-- SPLIT HERE -->\n"; # tag to know where to split
+$PROTECTTAG = "_ThisIsProtected_"; # tag to recognize protected sections
+$html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//EN">';
+
+#
+# language dependent constants
+#
+#$LDC_SEE = 'see';
+#$LDC_SECTION = 'section';
+#$LDC_IN = 'in';
+#$LDC_TOC = 'Table of Contents';
+#$LDC_GOTO = 'Go to the';
+#$LDC_FOOT = 'Footnotes';
+# TODO: @def* shortcuts
+
+#$user_sub{"email"} = "fix_email";
+
+#
+# pre-defined indices
+#
+%predefined_index = (
+ 'cp', 'c',
+ 'fn', 'f',
+ 'vr', 'v',
+ 'ky', 'k',
+ 'pg', 'p',
+ 'tp', 't',
+ );
+
+#
+# valid indices
+#
+%valid_index = (
+ 'c', 1,
+ 'f', 1,
+ 'v', 1,
+ 'k', 1,
+ 'p', 1,
+ 't', 1,
+ );
+
+#
+# texinfo section names to level
+#
+%sec2level = (
+ 'top', 0,
+ 'chapter', 1,
+ 'unnumbered', 1,
+ 'majorheading', 1,
+ 'chapheading', 1,
+ 'appendix', 1,
+ 'section', 2,
+ 'unnumberedsec', 2,
+ 'heading', 2,
+ 'appendixsec', 2,
+ 'appendixsection', 2,
+ 'subsection', 3,
+ 'unnumberedsubsec', 3,
+ 'subheading', 3,
+ 'appendixsubsec', 3,
+ 'subsubsection', 4,
+ 'unnumberedsubsubsec', 4,
+ 'subsubheading', 4,
+ 'appendixsubsubsec', 4,
+ );
+
+#
+# accent map, TeX command to ISO name
+#
+%accent_map = (
+ '"', 'uml',
+ '~', 'tilde',
+ '^', 'circ',
+ '`', 'grave',
+ '\'', 'acute',
+ );
+
+#
+# texinfo "simple things" (@foo) to HTML ones
+#
+%simple_map = (
+ # cf. makeinfo.c
+ "*", "<BR>", # HTML+
+ " ", " ",
+ "\n", "\n",
+ "|", "",
+ # spacing commands
+ ":", "",
+ "!", "!",
+ "?", "?",
+ ".", ".",
+ );
+
+#
+# texinfo "things" (@foo{}) to HTML ones
+#
+%things_map = (
+ 'TeX', 'TeX',
+ 'br', '<P>', # paragraph break
+ 'bullet', '*',
+ 'copyright', '(C)',
+ 'dots', '...',
+ 'equiv', '==',
+ 'error', 'error-->',
+ 'expansion', '==>',
+ 'minus', '-',
+ 'point', '-!-',
+ 'print', '-|',
+ 'result', '=>',
+ 'today', $TODAY,
+ );
+
+#
+# texinfo styles (@foo{bar}) to HTML ones
+#
+%style_map = (
+ 'asis', '',
+ 'b', 'B',
+ 'cite', 'CITE',
+ 'code', 'CODE',
+ 'ctrl', '&do_ctrl', # special case
+ 'dfn', 'STRONG', # DFN tag is illegal in the standard
+ 'dmn', '', # useless
+ 'email', '&fix_email', # special
+ 'emph', 'EM',
+ 'file', '"TT', # will put quotes, cf. &apply_style
+ 'i', 'I',
+ 'kbd', 'KBD',
+ 'key', 'KBD',
+ 'r', '', # unsupported
+ 'samp', '"SAMP', # will put quotes, cf. &apply_style
+ 'sc', '&do_sc', # special case
+ 'strong', 'STRONG',
+ 't', 'TT',
+ 'titlefont', '', # useless
+ 'image', '&fix_image', # Image
+ 'url', '&fix_url', # URL
+ 'uref', '&fix_uref', # URL Reference
+ 'var', 'VAR',
+ 'w', '', # unsupported
+ );
+
+#
+# texinfo format (@foo/@end foo) to HTML ones
+#
+%format_map = (
+ 'display', 'PRE',
+ 'example', 'PRE',
+ 'format', 'PRE',
+ 'lisp', 'PRE',
+ 'quotation', 'BLOCKQUOTE',
+ 'smallexample', 'PRE',
+ 'smalllisp', 'PRE',
+ # lists
+ 'itemize', 'UL',
+ 'enumerate', 'OL',
+ # poorly supported
+ 'flushleft', 'PRE',
+ 'flushright', 'PRE',
+ );
+
+#
+# texinfo definition shortcuts to real ones
+#
+%def_map = (
+ # basic commands
+ 'deffn', 0,
+ 'defvr', 0,
+ 'deftypefn', 0,
+ 'deftypevr', 0,
+ 'defcv', 0,
+ 'defop', 0,
+ 'deftp', 0,
+ # basic x commands
+ 'deffnx', 0,
+ 'defvrx', 0,
+ 'deftypefnx', 0,
+ 'deftypevrx', 0,
+ 'defcvx', 0,
+ 'defopx', 0,
+ 'deftpx', 0,
+ # shortcuts
+ 'defun', 'deffn Function',
+ 'defmac', 'deffn Macro',
+ 'defspec', 'deffn {Special Form}',
+ 'defvar', 'defvr Variable',
+ 'defopt', 'defvr {User Option}',
+ 'deftypefun', 'deftypefn Function',
+ 'deftypevar', 'deftypevr Variable',
+ 'defivar', 'defcv {Instance Variable}',
+ 'defmethod', 'defop Method',
+ # x shortcuts
+ 'defunx', 'deffnx Function',
+ 'defmacx', 'deffnx Macro',
+ 'defspecx', 'deffnx {Special Form}',
+ 'defvarx', 'defvrx Variable',
+ 'defoptx', 'defvrx {User Option}',
+ 'deftypefunx', 'deftypefnx Function',
+ 'deftypevarx', 'deftypevrx Variable',
+ 'defivarx', 'defcvx {Instance Variable}',
+ 'defmethodx', 'defopx Method',
+ );
+
+#
+# things to skip
+#
+%to_skip = (
+ # comments
+ 'c', 1,
+ 'comment', 1,
+ # useless
+ 'contents', 1,
+ 'shortcontents', 1,
+ 'summarycontents', 1,
+ 'footnotestyle', 1,
+ 'end ifclear', 1,
+ 'end ifset', 1,
+ 'titlepage', 1,
+ 'end titlepage', 1,
+ # unsupported commands (formatting)
+ 'afourpaper', 1,
+ 'cropmarks', 1,
+ 'finalout', 1,
+ 'headings', 1,
+ 'need', 1,
+ 'page', 1,
+ 'setchapternewpage', 1,
+ 'everyheading', 1,
+ 'everyfooting', 1,
+ 'evenheading', 1,
+ 'evenfooting', 1,
+ 'oddheading', 1,
+ 'oddfooting', 1,
+ 'smallbook', 1,
+ 'vskip', 1,
+ 'filbreak', 1,
+ # unsupported formats
+ 'cartouche', 1,
+ 'end cartouche', 1,
+ 'group', 1,
+ 'end group', 1,
+ );
+
+#+++############################################################################
+# #
+# Argument parsing, initialisation #
+# #
+#---############################################################################
+
+%value = (); # hold texinfo variables
+
+$use_bibliography = 1;
+$use_acc = 0;
+$debug = 0;
+$doctype = '';
+$check = 0;
+$expandinfo = 0;
+$use_glossary = 0;
+$invisible_mark = '';
+$use_iso = 0;
+@include_dirs = ();
+$show_menu = 0;
+$number_sections = 0;
+$split_node = 0;
+$split_chapter = 0;
+$monolithic = 0;
+$verbose = 0;
+$opt_use_numbers = 0;
+$opt_empty_headers = 0;
+$opt_special_links = "";
+$usage = <<EOT;
+This is $THISPROG
+To convert a Texinfo file to HMTL: $0 [options] file
+where options can be:
+-expandinfo : use \@ifinfo sections, not \@iftex
+-glossary : handle a glossary
+-invisible name: use 'name' as an invisible anchor
+-I dir : search also for files in 'dir'
+-Dvar=value : define a variable, as with \@set
+-menu : handle menus
+-monolithic : output only one file including ToC
+-number : number sections
+-split_chapter : split on main sections
+-split_node : split on nodes
+-ref_num : use numeric names when spliting
+-empty_headers : no headers and implicit links (for inclusion into other documents)
+-usage : print usage instructions
+-verbose : verbose output
+To check converted files: $0 -check [-verbose] files
+EOT
+ #
+while ($#ARGV >= 0 && $ARGV[0] =~ /^-/)
+{
+ $_ = shift(@ARGV);
+ if (/^-acc$/) { $use_acc = 1; next; }
+ if (/^-d(ebug)?(\d+)?$/) { $debug = $2 || shift(@ARGV); next; }
+ if (/^-doctype$/) { $doctype = shift(@ARGV); next; }
+ if (/^-c(heck)?$/) { $check = 1; next; }
+ if (/^-e(xpandinfo)?$/) { $expandinfo = 1; next; }
+ if (/^-g(lossary)?$/) { $use_glossary = 1; next; }
+ if (/^-i(nvisible)?$/) { $invisible_mark = shift(@ARGV); next; }
+ if (/^-iso$/) { $use_iso = 1; next; }
+ if (/^-I(.+)?$/) { push(@include_dirs, $2 || shift(@ARGV)); next; }
+ if (/^-D([a-zA-Z0-9]+)=?(.+)?$/)
+ { $value{$1} = $2 ? $2 : 1; next; }
+ if (/^-m(enu)?$/) { $show_menu = 1; next; }
+ if (/^-mono(lithic)?$/) { $monolithic = 1; next; }
+ if (/^-n(umber)?$/) { $number_sections = 1; next; }
+ if (/^-ref_num$/) { $opt_use_numbers = 1; next; }
+ if (/^-empty_headers$/) { $opt_empty_headers = 1; next; }
+ if (/^-special_links$/) { $opt_special_links = $2 || shift(@ARGV); next; }
+ if (/^-s(plit)?_?(n(ode)?|c(hapter)?)?$/) {
+ if ($2 =~ /^n/) {
+ $split_node = 1;
+ } else {
+ $split_chapter = 1;
+ }
+ next;
+ }
+ if (/^-v(erbose)?$/) { $verbose = 1; next; }
+ die $usage;
+}
+if ($check) {
+ die $usage unless @ARGV > 0;
+ &check;
+ exit;
+}
+
+die "Can't use -special_links with -ref_num.\n"
+ if $opt_special_links && $opt_use_numbers;
+die "Must have -split_node with -special_links.\n"
+ if $opt_special_links && !$split_node;
+
+if (($split_node || $split_chapter) && $monolithic) {
+ warn "Can't use -monolithic with -split, -monolithic ignored.\n";
+ $monolithic = 0;
+}
+if ($expandinfo) {
+ $to_skip{'ifinfo'}++;
+ $to_skip{'end ifinfo'}++;
+} else {
+ $to_skip{'iftex'}++;
+ $to_skip{'end iftex'}++;
+}
+$invisible_mark = '<IMG SRC="invisible.xbm">' if $invisible_mark eq 'xbm';
+die $usage unless @ARGV == 1;
+$docu = shift(@ARGV);
+if ($docu =~ /.*\//) {
+ chop($docu_dir = $&);
+ $docu_name = $';
+} else {
+ $docu_dir = '.';
+ $docu_name = $docu;
+}
+unshift(@include_dirs, $docu_dir);
+$docu_name =~ s/\.te?x(i|info)?$//; # basename of the document
+
+$docu_doc = "$docu_name.html"; # document's contents
+$link_doc = $docu_doc;
+if ($monolithic) {
+ $docu_toc = $docu_foot = $docu_doc;
+} else {
+ $docu_toc = "${docu_name}_toc.html"; # document's table of contents
+ $docu_foot = "${docu_name}_foot.html"; # document's footnotes
+}
+
+#
+# variables
+#
+$value{'html'} = 1; # predefine html (the output format)
+$value{'texi2html'} = '1.52'; # predefine texi2html (the translator)
+# _foo: internal to track @foo
+foreach ('_author', '_title', '_subtitle',
+ '_settitle', '_setfilename') {
+ $value{$_} = ''; # prevent -w warnings
+}
+%node2sec = (); # node to section name
+%node2href = (); # node to HREF
+%bib2href = (); # bibliography reference to HREF
+%gloss2href = (); # glossary term to HREF
+@sections = (); # list of sections
+%tag2pro = (); # protected sections
+
+#
+# initial indexes
+#
+$bib_num = 0;
+$foot_num = 0;
+$gloss_num = 0;
+$idx_num = 0;
+$sec_num = 0;
+$doc_num = 0;
+$current_chapter_link = "";
+@maybe_wrong_links = ();
+$html_num = 0;
+
+#
+# can I use ISO8879 characters? (HTML+)
+#
+if ($use_iso) {
+ $things_map{'bullet'} = "&bull;";
+ $things_map{'copyright'} = "&copy;";
+ $things_map{'dots'} = "&hellip;";
+ $things_map{'equiv'} = "&equiv;";
+ $things_map{'expansion'} = "&rarr;";
+ $things_map{'point'} = "&lowast;";
+ $things_map{'result'} = "&rArr;";
+}
+
+#
+# read texi2html extensions (if any)
+#
+$extensions = 'texi2html.ext'; # extensions in working directory
+if (-f $extensions) {
+ print "# reading extensions from $extensions\n" if $verbose;
+ require($extensions);
+}
+($progdir = $0) =~ s/[^\/]+$//;
+if ($progdir && ($progdir ne './'))
+{
+ $extensions = "${progdir}texi2html.ext"; # extensions in texi2html directory
+ if (-f $extensions) {
+ print "# reading extensions from $extensions\n" if $verbose;
+ require($extensions);
+ }
+}
+
+ print "# reading from $docu\n" if $verbose;
+
+#+++############################################################################
+# #
+# Pass 1: read source, handle command, variable, simple substitution #
+# #
+#---############################################################################
+
+@lines = (); # whole document
+@toc_lines = (); # table of contents
+$toplevel = 0; # top level seen in hierarchy
+$curlevel = 0; # current level in TOC
+$node = ''; # current node name
+$in_table = 0; # am I inside a table
+$table_type = ''; # type of table ('', 'f', 'v')
+@tables = (); # nested table support
+$in_bibliography = 0; # am I inside a bibliography
+$in_glossary = 0; # am I inside a glossary
+$in_top = 0; # am I inside the top node
+$in_pre = 0; # am I inside a preformatted section
+$in_list = 0; # am I inside a list
+$in_html = 0; # am I inside an HTML section
+$first_line = 1; # is it the first line
+$dont_html = 0; # don't protect HTML on this line
+$split_num = 0; # split index
+$deferred_ref = ''; # deferred reference for indexes
+@html_stack = (); # HTML elements stack
+$html_element = ''; # current HTML element
+&html_reset;
+
+# build code for simple substitutions
+# the maps used (%simple_map and %things_map) MUST be aware of this
+# watch out for regexps, / and escaped characters!
+$subst_code = '';
+foreach (keys(%simple_map)) {
+ ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars
+ $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n";
+}
+foreach (keys(%things_map)) {
+ $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n";
+}
+if ($use_acc) {
+ # accentuated characters
+ foreach (keys(%accent_map)) {
+ if ($_ eq "`") {
+ $subst_code .= "s/$;3";
+ } elsif ($_ eq "'") {
+ $subst_code .= "s/$;4";
+ } else {
+ $subst_code .= "s/\\\@\\$_";
+ }
+ $subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n";
+ }
+}
+eval("sub simple_substitutions { $subst_code }");
+
+&init_input;
+READ_LINE: while ($_ = &next_line)
+{
+ #
+ # remove \input on the first lines only
+ #
+ if ($first_line) {
+ next if /^\\input/;
+ $first_line = 0;
+ }
+ #
+ # parse texinfo tags
+ #
+ $tag = '';
+ $end_tag = '';
+ if (/^\s*\@end\s+(\w+)\b/) {
+ $end_tag = $1;
+ } elsif (/^\s*\@(\w+)\b/) {
+ $tag = $1;
+ }
+ #
+ # handle @ifhtml / @end ifhtml
+ #
+ if ($in_html) {
+ if ($end_tag eq 'ifhtml') {
+ $in_html = 0;
+ } else {
+ $tag2pro{$in_html} .= $_;
+ }
+ next;
+ } elsif ($tag eq 'ifhtml') {
+ $in_html = $PROTECTTAG . ++$html_num;
+ push(@lines, $in_html);
+ next;
+ }
+ #
+ # try to skip the line
+ #
+ if ($end_tag) {
+ next if $to_skip{"end $end_tag"};
+ } elsif ($tag) {
+ next if $to_skip{$tag};
+ last if $tag eq 'bye';
+ }
+ if ($in_top) {
+ # parsing the top node
+ if ($tag eq 'node' || $tag eq 'include' || $sec2level{$tag}) {
+ # no more in top
+ $in_top = 0;
+ } else {
+ # skip it
+ next;
+ }
+ }
+ #
+ # try to remove inlined comments
+ # syntax from tex-mode.el comment-start-skip
+ #
+ s/((^|[^\s*\@])(\@\@)*)\@c(omment)? .*/$1/;
+ # non-@ substitutions cf. texinfmt.el
+ # Since these changes break code examples in the source they were removed. David 990729
+ #s/``/\"/g;
+ #s/''/\"/g;
+ s/([\w ])---([\w ])/$1--$2/g;
+ #
+ # analyze the tag
+ #
+ if ($tag) {
+ # skip lines
+ &skip_until($tag), next if $tag eq 'ignore';
+ if ($expandinfo) {
+ &skip_until($tag), next if $tag eq 'iftex';
+ } else {
+ &skip_until($tag), next if $tag eq 'ifinfo';
+ }
+ &skip_until($tag), next if $tag eq 'tex';
+ # handle special tables
+ if ($tag eq 'table') {
+ $table_type = '';
+ } elsif ($tag eq 'ftable') {
+ $tag = 'table';
+ $table_type = 'f';
+ } elsif ($tag eq 'vtable') {
+ $tag = 'table';
+ $table_type = 'v';
+ }
+ # special cases
+ if ($tag eq 'top' || ($tag eq 'node' && /^\s*\@node\s+top\s*,/i)) {
+ $in_top = 1;
+ @lines = (); # ignore all lines before top (title page garbage)
+ next;
+ } elsif ($tag eq 'node') {
+ $in_top = 0;
+ warn "$ERROR Bad node line: $_" unless $_ =~ /^\s*\@node\s$NODESRE$/o;
+ $_ = &protect_html($_); # if node contains '&' for instance
+ s/^\s*\@node\s+//;
+ ($node) = split(/,/);
+ &normalise_node($node);
+ if ($split_node) {
+ ($doc_node_name[$doc_num + 1] = $node) =~ s|[ /]|_|g;
+ $doc_node_name_links[$doc_num + 1] = $current_chapter_link;
+ &next_doc;
+ push(@lines, $SPLITTAG) if $split_num++;
+ push(@sections, $node);
+ }
+ next;
+ } elsif ($tag eq 'include') {
+ if (/^\s*\@include\s+($FILERE)\s*$/o) {
+ $file = $1;
+ unless (-e $file) {
+ foreach $dir (@include_dirs) {
+ $file = "$dir/$1";
+ last if -e $file;
+ }
+ }
+ if (-e $file) {
+ &open($file);
+ print "# including $file\n" if $verbose;
+ } else {
+ warn "$ERROR Can't find $file, skipping";
+ }
+ } else {
+ warn "$ERROR Bad include line: $_";
+ }
+ next;
+ } elsif ($tag eq 'ifclear') {
+ if (/^\s*\@ifclear\s+($VARRE)\s*$/o) {
+ next unless defined($value{$1});
+ &skip_until($tag);
+ } else {
+ warn "$ERROR Bad ifclear line: $_";
+ }
+ next;
+ } elsif ($tag eq 'ifset') {
+ if (/^\s*\@ifset\s+($VARRE)\s*$/o) {
+ next if defined($value{$1});
+ &skip_until($tag);
+ } else {
+ warn "$ERROR Bad ifset line: $_";
+ }
+ next;
+ } elsif ($tag eq 'menu') {
+ unless ($show_menu) {
+ &skip_until($tag);
+ next;
+ }
+ &html_push_if($tag);
+ push(@lines, &html_debug("\n", __LINE__));
+ } elsif ($format_map{$tag}) {
+ $in_pre = 1 if $format_map{$tag} eq 'PRE';
+ &html_push_if($format_map{$tag});
+ push(@lines, &html_debug("\n", __LINE__));
+ $in_list++ if $format_map{$tag} eq 'UL' || $format_map{$tag} eq 'OL' ;
+ push(@lines, &debug("<$format_map{$tag}>\n", __LINE__));
+ next;
+ } elsif ($tag eq 'table') {
+ if (/^\s*\@[fv]?table\s+\@(\w+)\s*$/) {
+ $in_table = $1;
+ unshift(@tables, join($;, $table_type, $in_table));
+ push(@lines, &debug("<DL COMPACT>\n", __LINE__));
+ &html_push_if('DL');
+ push(@lines, &html_debug("\n", __LINE__));
+ } else {
+ warn "$ERROR Bad table line: $_";
+ }
+ next;
+ } elsif ($tag eq 'multitable') {
+ if (/^\s*\@multitable\s*\@columnfractions\s+([\.\d\s]+)\s*$/ ||
+ /^\s*\@multitable\s*({[^{}]+})+\s*$/)
+ {
+ $in_multitable = 1;
+ html_push('TABLE');
+ my($col_list) = $1;
+ $multitable_cols = ($col_list =~ /\@columnfractions/ ? s/[\d.]+\s+//g :
+ s/{[^{}]+}//g);
+ print "# Multitable with $multitable_cols columns\n"
+ if $debug and $DEBUG_USER;
+ push(@lines, &debug("<TABLE BORDER WIDTH=\"100%\">\n", __LINE__));
+ } else {
+ warn "$ERROR Bad table line: $_";
+ }
+ next;
+ } elsif ($tag eq 'synindex' || $tag eq 'syncodeindex') {
+ if (/^\s*\@$tag\s+(\w)\w\s+(\w)\w\s*$/) {
+ eval("*${1}index = *${2}index");
+ } else {
+ warn "$ERROR Bad syn*index line: $_";
+ }
+ next;
+ } elsif ($tag eq 'sp') {
+ push(@lines, &debug("<P>\n", __LINE__));
+ next;
+ } elsif ($tag eq 'setref') {
+ &protect_html; # if setref contains '&' for instance
+ if (/^\s*\@$tag\s*{($NODERE)}\s*$/) {
+ $setref = $1;
+ $setref =~ s/\s+/ /g; # normalize
+ $setref =~ s/ $//;
+ $node2sec{$setref} = $name;
+ $node2href{$setref} = "$link_doc#$docid";
+ push(@maybe_wrong_links, $setref);
+ } else {
+ warn "$ERROR Bad setref line: $_";
+ }
+ next;
+ } elsif ($tag eq 'defindex' || $tag eq 'defcodeindex') {
+ if (/^\s*\@$tag\s+(\w\w)\s*$/) {
+ $valid_index{$1} = 1;
+ } else {
+ warn "$ERROR Bad defindex line: $_";
+ }
+ next;
+ } elsif (defined($def_map{$tag})) {
+ if ($def_map{$tag}) {
+ s/^\s*\@$tag\s+//;
+ $tag = $def_map{$tag};
+ $_ = "\@$tag $_";
+ $tag =~ s/\s.*//;
+ }
+ } elsif (defined($user_sub{$tag})) {
+ s/^\s*\@$tag\s+//;
+ $sub = $user_sub{$tag};
+ print "# user $tag = $sub, arg: $_" if $debug & $DEBUG_USER;
+ if (defined(&$sub)) {
+ chop($_);
+ &$sub($_);
+ } else {
+ warn "$ERROR Bad user sub for $tag: $sub\n";
+ }
+ next;
+ }
+ if (defined($def_map{$tag})) {
+ s/^\s*\@$tag\s+//;
+ if ($tag =~ /x$/) {
+ # extra definition line
+ $tag = $`;
+ $is_extra = 1;
+ } else {
+ $is_extra = 0;
+ }
+ while (/\{([^\{\}]*)\}/) {
+ # this is a {} construct
+ ($before, $contents, $after) = ($`, $1, $');
+ # protect spaces
+ $contents =~ s/\s+/$;9/g;
+ # restore $_ protecting {}
+ $_ = "$before$;7$contents$;8$after";
+ }
+ @args = split(/\s+/, &protect_html($_));
+ foreach (@args) {
+ s/$;9/ /g; # unprotect spaces
+ s/$;7/\{/g; # ... {
+ s/$;8/\}/g; # ... }
+ }
+ $type = shift(@args);
+ $type =~ s/^\{(.*)\}$/$1/;
+ print "# def ($tag): {$type} ", join(', ', @args), "\n"
+ if $debug & $DEBUG_DEF;
+ $type .= ':'; # it's nicer like this
+ $name = shift(@args);
+ $name =~ s/^\{(.*)\}$/$1/;
+ if ($is_extra) {
+ $_ = &debug("<DT>", __LINE__);
+ } else {
+ $_ = &debug("<DL>\n<DT>", __LINE__);
+ }
+ if ($tag eq 'deffn' || $tag eq 'defvr' || $tag eq 'deftp') {
+ $_ .= "<U>$type</U> <B>$name</B>";
+ $_ .= " <I>@args</I>" if @args;
+ } elsif ($tag eq 'deftypefn' || $tag eq 'deftypevr'
+ || $tag eq 'defcv' || $tag eq 'defop') {
+ $ftype = $name;
+ $name = shift(@args);
+ $name =~ s/^\{(.*)\}$/$1/;
+ $_ .= "<U>$type</U> $ftype <B>$name</B>";
+ $_ .= " <I>@args</I>" if @args;
+ } else {
+ warn "$ERROR Unknown definition type: $tag\n";
+ $_ .= "<U>$type</U> <B>$name</B>";
+ $_ .= " <I>@args</I>" if @args;
+ }
+ $_ .= &debug("\n<DD>", __LINE__);
+ $name = &unprotect_html($name);
+ if ($tag eq 'deffn' || $tag eq 'deftypefn') {
+ unshift(@input_spool, "\@findex $name\n");
+ } elsif ($tag eq 'defop') {
+ unshift(@input_spool, "\@findex $name on $ftype\n");
+ } elsif ($tag eq 'defvr' || $tag eq 'deftypevr' || $tag eq 'defcv') {
+ unshift(@input_spool, "\@vindex $name\n");
+ } else {
+ unshift(@input_spool, "\@tindex $name\n");
+ }
+ $dont_html = 1;
+ }
+ } elsif ($end_tag) {
+ if ($format_map{$end_tag}) {
+ $in_pre = 0 if $format_map{$end_tag} eq 'PRE';
+ $in_list-- if $format_map{$end_tag} eq 'UL' || $format_map{$end_tag} eq 'OL' ;
+ &html_pop_if('LI', 'P');
+ &html_pop_if();
+ push(@lines, &debug("</$format_map{$end_tag}>\n", __LINE__));
+ push(@lines, &html_debug("\n", __LINE__));
+ } elsif ($end_tag eq 'table' ||
+ $end_tag eq 'ftable' ||
+ $end_tag eq 'vtable') {
+ shift(@tables);
+ if (@tables) {
+ ($table_type, $in_table) = split($;, $tables[0]);
+ } else {
+ $in_table = 0;
+ $table_type = '';
+ }
+ push(@lines, "</DL>\n");
+ &html_pop_if('DD');
+ &html_pop_if();
+ } elsif ($end_tag eq 'multitable') {
+ print "# end of multitable with $multitable_cols columns\n"
+ if $debug and $DEBUG_USER;
+ $in_multitable = 0;
+ push(@lines, "</TR>\n");
+ &html_pop_if('TR');
+ push(@lines, "</TABLE>\n");
+&html_pop_if('TABLE');
+ } elsif (defined($def_map{$end_tag})) {
+ push(@lines, &debug("</DL>\n", __LINE__));
+ } elsif ($end_tag eq 'menu') {
+ &html_pop_if();
+ push(@lines, $_); # must keep it for pass 2
+ }
+ next;
+ }
+ #
+ # misc things
+ #
+ # protect texi and HTML things
+ &protect_texi;
+ $_ = &protect_html($_) unless $dont_html;
+ $dont_html = 0;
+ # substitution (unsupported things)
+ s/^\s*\@center\s+//g;
+ s/^\s*\@exdent\s+//g;
+ s/\@noindent\s+//g;
+ s/\@refill\s+//g;
+ # other substitutions
+ &simple_substitutions;
+ s/\@value{($VARRE)}/$value{$1}/eg;
+ s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4
+ s|\s+\@tab\s*| </TD><TD> |g if ($in_multitable);
+
+ #
+ # analyze the tag again
+ #
+ if ($tag) {
+ if (defined($sec2level{$tag}) && $sec2level{$tag} > 0) {
+ if (/^\s*\@$tag\s+(.+)$/) {
+ $name = $1;
+ $name =~ s/\s+$//;
+ $level = $sec2level{$tag};
+ $name = &update_sec_num($tag, $level) . " $name"
+ if $number_sections && $tag !~ /^unnumbered/;
+ if ($tag =~ /heading$/) {
+ push(@lines, &html_debug("\n", __LINE__));
+ if ($html_element ne 'body') {
+ # We are in a nice pickle here. We are trying to get a H? heading
+ # even though we are not in the body level. So, we convert
+ # it to a nice, bold, line by itself.
+ $_ = &debug("\n\n<P><STRONG>$name</STRONG></P>\n\n", __LINE__);
+ } else {
+ $_ = &debug("<H$level>$name</H$level>\n", __LINE__);
+ &html_push_if('body');
+ }
+ print "# heading, section $name, level $level\n"
+ if $debug & $DEBUG_TOC;
+ } else {
+ if ($split_chapter) {
+ unless ($toplevel) {
+ # first time we see a "section"
+ unless ($level == 1) {
+ warn "$ERROR The first section found is not of level 1: $_";
+ warn "$ERROR I'll split on sections of level $level...\n";
+ }
+ $toplevel = $level;
+ };
+ if ($level == $toplevel) {
+ print "# Splitting at section $name\n"
+ if $debug & $DEBUG_TOC;
+ ($doc_node_name[$doc_num + 1] = $node) =~ s|[ /]|_|g;
+ &next_doc;
+ push(@lines, $SPLITTAG) if $split_num++;
+ push(@sections, $name);
+ }
+ } elsif ($split_node && $opt_special_links) {
+ $toplevel = $level unless $toplevel;
+ if ($level == $toplevel) {
+ ($current_chapter_link = $node) =~ s|[ /]|_|g;
+ # Set this again to the right value.
+ $doc_node_name_links[$doc_num] = $current_chapter_link;
+ ($docu_doc, $link_doc) = &doc_name($doc_num);
+ }
+ }
+ $sec_num++;
+ # Was "SEC$sec_num"
+ ($docid = "$node") =~ s|[ /]|_|g;
+ ($tocid = "$node") =~ s|[ /]|_|g;
+$docid = "SEC$sec_num" unless $docid;
+$tocid = "SEC$sec_num" unless $tocid;
+ # check biblio and glossary
+ $in_bibliography =
+ ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*bibliography$/i);
+ $in_glossary = ($name =~ /^([A-Z]|\d+)?(\.\d+)*\s*glossary$/i);
+ # check node
+ if ($node) {
+ if ($node2sec{$node}) {
+ warn "$ERROR Duplicate node found: $node\n";
+ } else {
+ $node2sec{$node} = $name;
+ $node2href{$node} = "$link_doc#$docid";
+ push(@maybe_wrong_links, $node);
+ print "# node $node, section $name, level $level\n"
+ if $debug & $DEBUG_TOC;
+ }
+ $node = '';
+ } else {
+ print "# no node, section $name, level $level\n"
+ if $debug & $DEBUG_TOC;
+ }
+ # update TOC
+ while ($level > $curlevel) {
+ $curlevel++;
+ push(@toc_lines, "<UL>\n");
+ }
+ while ($level < $curlevel) {
+ $curlevel--;
+ push(@toc_lines, "</UL>\n");
+ }
+ $_ = "<LI>" . &anchor($tocid, "$link_doc#$docid", $name, 1);
+ push(@toc_lines, &substitute_style($_));
+ # update DOC
+ push(@lines, &html_debug("\n", __LINE__));
+ &html_reset;
+ $_ = "<H$level>".&anchor($docid, $opt_empty_headers ? "" : "$docu_toc#$tocid",
+ $name)."</H$level>\n";
+ $_ = &debug($_, __LINE__);
+ push(@lines, &html_debug("\n", __LINE__));
+ }
+ # update DOC
+ foreach $line (split(/\n+/, $_)) {
+ push(@lines, "$line\n");
+ }
+ next;
+ } else {
+ warn "$ERROR Bad section line: $_";
+ }
+ } else {
+ # track variables
+ $value{$1} = $2, next if /^\s*\@set\s+($VARRE)\s+(.*)$/o;
+ delete $value{$1}, next if /^\s*\@clear\s+($VARRE)\s*$/o;
+ # store things
+ $value{'_setfilename'} = $1, next if /^\s*\@setfilename\s+(.*)$/;
+ $value{'_settitle'} = $1, next if /^\s*\@settitle\s+(.*)$/;
+ $value{'_author'} .= "$1\n", next if /^\s*\@author\s+(.*)$/;
+ $value{'_subtitle'} .= "$1\n", next if /^\s*\@subtitle\s+(.*)$/;
+ $value{'_title'} .= "$1\n", next if /^\s*\@title\s+(.*)$/;
+ # index
+ if (/^\s*\@(..?)index\s+/) {
+ unless ($valid_index{$1}) {
+ warn "$ERROR Undefined index command: $_";
+ next;
+ }
+ $id = 'IDX' . ++$idx_num;
+ $index = $1 . 'index';
+ $what = &substitute_style($');
+ $what =~ s/\s+$//;
+ print "# found $index for '$what' id $id\n"
+ if $debug & $DEBUG_INDEX;
+ eval(<<EOC);
+ if (defined(\$$index\{\$what\})) {
+ \$$index\{\$what\} .= "$;$link_doc#$id";
+ } else {
+ \$$index\{\$what\} = "$link_doc#$id";
+ }
+EOC
+ #
+ # dirty hack to see if I can put an invisible anchor...
+ #
+ if ($html_element eq 'P' ||
+ $html_element eq 'LI' ||
+ $html_element eq 'DT' ||
+ $html_element eq 'DD' ||
+ $html_element eq 'ADDRESS' ||
+ $html_element eq 'B' ||
+ $html_element eq 'BLOCKQUOTE' ||
+ $html_element eq 'PRE' ||
+ $html_element eq 'SAMP') {
+ push(@lines, &anchor($id, '', $invisible_mark, !$in_pre));
+ } elsif ($html_element eq 'body') {
+ push(@lines, &debug("<P>\n", __LINE__));
+ push(@lines, &anchor($id, '', $invisible_mark, !$in_pre));
+ &html_push('P');
+ } elsif ($html_element eq 'DL' ||
+ $html_element eq 'UL' ||
+ $html_element eq 'OL' ||
+ $html_element eq 'TR') {
+ $deferred_ref .=
+ &anchor($id, '', $invisible_mark, !$in_pre) . " ";
+ }
+ next;
+ }
+ # list item
+ if (/^\s*\@itemx?\s+/)
+ {
+ $what = $';
+ $what =~ s/\s+$//;
+
+ # add an index before the item if applicable
+ if ($table_type ne '' && !$in_multitable) {
+ print "# Adding table index (type $table_type) for $what\n"
+ if $debug & $DEBUG_INDEX;
+ # This is realy ugly. We should do a pass before this to
+ # add index entrys before instead.
+ if ($global_added_this_index) {
+ $global_added_this_index = 0;
+ } else {
+ unshift(@input_spool, "\@${table_type}index $what\n", $_);
+ $global_added_this_index = 1;
+ next READ_LINE;
+ }
+ }
+
+ if ($in_bibliography && $use_bibliography) {
+ if ($what =~ /^$BIBRE$/o) {
+ $id = 'BIB' . ++$bib_num;
+ $bib2href{$what} = "$link_doc#$id";
+ print "# found bibliography for '$what' id $id\n"
+ if $debug & $DEBUG_BIB;
+ $what = &anchor($id, '', $what);
+ }
+ } elsif ($in_glossary && $use_glossary) {
+ $id = 'GLOSS' . ++$gloss_num;
+ $entry = $what;
+ $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
+ $gloss2href{$entry} = "$link_doc#$id";
+ print "# found glossary for '$entry' id $id\n"
+ if $debug & $DEBUG_GLOSS;
+ $what = &anchor($id, '', $what);
+ }
+ if ($in_multitable)
+ {
+ # All this is a **HACK**.
+ # It does only work for a FEW SIMPLE CASES !!!
+ push(@lines, &debug("</TR>\n", __LINE__))
+ unless $html_element eq 'TABLE';;
+&html_pop_if('TR');
+ $what =~ s|\s+\@tab\s*| </TD><TD> |g;
+ push(@lines, &debug("<TR><TD>$what\n", __LINE__));
+ &html_push('TR');
+ if ($deferred_ref)
+ {
+ push(@lines, &debug("$deferred_ref\n", __LINE__));
+ $deferred_ref = '';
+ }
+ next;
+ }
+ else
+ {
+ &html_pop_if('P');
+ if ($html_element eq 'DL' || $html_element eq 'DD') {
+ if ($things_map{$in_table} && !$what) {
+ # special case to allow @table @bullet for instance
+ push(@lines, &debug("<DT>$things_map{$in_table}\n", __LINE__));
+ } else {
+ push(@lines, &debug("<DT>\@$in_table\{$what\}\n", __LINE__));
+ }
+ push(@lines, "<DD>");
+ &html_push('DD') unless $html_element eq 'DD';
+ # Old index add was here
+ } else {
+ push(@lines, &debug("<LI>$what\n", __LINE__));
+ &html_push('LI') unless $html_element eq 'LI';
+ }
+ push(@lines, &html_debug("\n", __LINE__));
+ if ($deferred_ref) {
+ push(@lines, &debug("$deferred_ref\n", __LINE__));
+ $deferred_ref = '';
+ }
+ next;
+ }
+ }
+ }
+ }
+ # paragraph separator
+ if ($_ eq "\n") {
+ next if $#lines >= 0 && $lines[$#lines] eq "\n";
+ if ($html_element eq 'P') {
+ push(@lines, "\n");
+ $_ = &debug("</P>\n", __LINE__);
+ &html_pop;
+ }
+ } elsif ($html_element eq 'body' || $html_element eq 'BLOCKQUOTE') {
+ push(@lines, "<P>\n");
+ &html_push('P');
+ $_ = &debug($_, __LINE__);
+ }
+ # otherwise
+ push(@lines, $_);
+}
+
+# finish TOC
+$level = 0;
+while ($level < $curlevel)
+{
+ $curlevel--;
+ push(@toc_lines, "</UL>\n");
+}
+
+print "# end of pass 1\n" if $verbose;
+
+#+++############################################################################
+# #
+# Pass 2/3: handle style, menu, index, cross-reference #
+# #
+#---############################################################################
+
+@lines2 = (); # whole document (2nd pass)
+@lines3 = (); # whole document (3rd pass)
+$in_menu = 0; # am I inside a menu
+
+while (@lines)
+{
+ $_ = shift(@lines);
+ #
+ # special case (protected sections)
+ #
+ if (/^$PROTECTTAG/o) {
+ push(@lines2, $_);
+ next;
+ }
+ #
+ # menu
+ #
+ $in_menu = 1, push(@lines2, &debug("<UL>\n", __LINE__)), next if /^\s*\@menu\b/;
+ $in_menu = 0, push(@lines2, &debug("</UL>\n", __LINE__)), next if /^\s*\@end\s+menu\b/;
+ if ($in_menu) {
+ if (/^\*\s+($NODERE)::/o) {
+ $descr = $';
+ chop($descr);
+ &menu_entry($1, $1, $descr);
+ } elsif (/^\*\s+(.+):\s+([^\t,\.\n]+)[\t,\.\n]/) {
+ $descr = $';
+ chop($descr);
+ &menu_entry($1, $2, $descr);
+ } elsif (/^\*/) {
+ warn "$ERROR Bad menu line: $_";
+ } else { # description continued?
+ push(@lines2, $_);
+ }
+ next;
+ }
+ #
+ # printindex
+ #
+ if (/^\s*\@printindex\s+(\w\w)\b/) {
+ local($index, *ary, @keys, $key, $letter, $last_letter, @refs);
+ if ($predefined_index{$1}) {
+ $index = $predefined_index{$1} . 'index';
+ } else {
+ $index = $1 . 'index';
+ }
+ eval("*ary = *$index");
+ @keys = keys(%ary);
+ foreach $key (@keys) {
+ $_ = $key;
+ 1 while s/<(\w+)>\`(.*)\'<\/\1>/$2/; # remove HTML tags with quotes
+ 1 while s/<(\w+)>(.*)<\/\1>/$2/; # remove HTML tags
+ $_ = &unprotect_html($_);
+ &unprotect_texi;
+ tr/A-Z/a-z/; # lowercase
+ $key2alpha{$key} = $_;
+ print "# index $key sorted as $_\n"
+ if $key ne $_ && $debug & $DEBUG_INDEX;
+ }
+ $last_letter = undef;
+ foreach $key (sort byalpha @keys) {
+ $letter = substr($key2alpha{$key}, 0, 1);
+ $letter = substr($key2alpha{$key}, 0, 2) if $letter eq $;;
+ $letter = " " unless $letter =~ /[a-zA-Z]/;
+ if (!defined($last_letter) || $letter ne $last_letter) {
+ push(@lines2, "</DIR>\n") if defined($last_letter);
+ push(@lines2, "<H2>" . &protect_html(uc($letter)) . "</H2>\n");
+ push(@lines2, "<DIR>\n");
+ $last_letter = $letter;
+ }
+ @refs = ();
+ foreach (split(/$;/, $ary{$key})) {
+ push(@refs, &anchor('', $_, $key, 0));
+ }
+ push(@lines2, "<LI>" . join(", ", @refs) . "\n");
+ }
+ push(@lines2, "</DIR>\n") if defined($last_letter);
+ next;
+ }
+ #
+ # simple style substitutions
+ #
+ $_ = &substitute_style($_);
+ #
+ # xref
+ #
+ while (/\@(x|px|info|)ref{($XREFRE)(}?)/o) {
+ # note: Texinfo may accept other characters
+ ($type, $nodes, $full) = ($1, $2, $3);
+ ($before, $after) = ($`, $');
+ if (! $full && $after) {
+ warn "$ERROR Bad xref (no ending } on line): $_";
+ $_ = "$before$;0${type}ref\{$nodes$after";
+ next; # while xref
+ }
+ if ($type eq 'x') {
+ $type = 'See ';
+ } elsif ($type eq 'px') {
+ $type = 'see ';
+ } elsif ($type eq 'info') {
+ $type = 'See Info';
+ } elsif ($type eq 'u') {
+ $type = 'See ';
+ } else {
+ $type = '';
+ }
+ unless ($full) {
+ $next = shift(@lines);
+ $next = &substitute_style($next);
+ chop($nodes); # remove final newline
+ if ($next =~ /\}/) { # split on 2 lines
+ $nodes .= " $`";
+ $after = $';
+ } else {
+ $nodes .= " $next";
+ $next = shift(@lines);
+ $next = &substitute_style($next);
+ chop($nodes);
+ if ($next =~ /\}/) { # split on 3 lines
+ $nodes .= " $`";
+ $after = $';
+ } else {
+ warn "$ERROR Bad xref (no ending }): $_";
+ $_ = "$before$;0xref\{$nodes$after";
+ unshift(@lines, $next);
+ next; # while xref
+ }
+ }
+ }
+ $nodes =~ s/\s+/ /g; # remove useless spaces
+ @args = split(/\s*,\s*/, $nodes);
+ $node = $args[0]; # the node is always the first arg
+ &normalise_node($node);
+ $sec = $node2sec{$node};
+ if (@args == 5) { # reference to another manual
+ $sec = $args[2] || $node;
+ $man = $args[4] || $args[3];
+ $_ = "${before}${type}section `$sec' in \@cite{$man}$after";
+ } elsif ($type =~ /Info/) { # inforef
+ warn "$ERROR Wrong number of arguments: $_" unless @args == 3;
+ ($nn, $_, $in) = @args;
+ $_ = "${before}${type} file `$in', node `$nn'$after";
+ } elsif ($sec) {
+ $href = $node2href{$node};
+ $_ = "${before}${type}section " . &anchor('', $href, $sec) . $after;
+ } else {
+ warn "$ERROR Undefined node ($node): $_";
+ $_ = "$before$;0xref{$nodes}$after";
+ }
+ }
+ #
+ # try to guess bibliography references or glossary terms
+ #
+ # This checked for NAME="SEC\d". The current version is probably broken.
+ unless (/^<H\d><A NAME=\"/) {
+ if ($use_bibliography) {
+ $done = '';
+ while (/$BIBRE/o) {
+ ($pre, $what, $post) = ($`, $&, $');
+ $href = $bib2href{$what};
+ if (defined($href) && $post !~ /^[^<]*<\/A>/) {
+ $done .= $pre . &anchor('', $href, $what);
+ } else {
+ $done .= "$pre$what";
+ }
+ $_ = $post;
+ }
+ $_ = $done . $_;
+ }
+ if ($use_glossary) {
+ $done = '';
+ while (/\b\w+\b/) {
+ ($pre, $what, $post) = ($`, $&, $');
+ $entry = $what;
+ $entry =~ tr/A-Z/a-z/ unless $entry =~ /^[A-Z\s]+$/;
+ $href = $gloss2href{$entry};
+ if (defined($href) && $post !~ /^[^<]*<\/A>/) {
+ $done .= $pre . &anchor('', $href, $what);
+ } else {
+ $done .= "$pre$what";
+ }
+ $_ = $post;
+ }
+ $_ = $done . $_;
+ }
+ }
+ # otherwise
+ push(@lines2, $_);
+}
+print "# end of pass 2\n" if $verbose;
+
+#
+# split style substitutions
+#
+while (@lines2)
+{
+ $_ = shift(@lines2);
+ #
+ # special case (protected sections)
+ #
+ if (/^$PROTECTTAG/o) {
+ push(@lines3, $_);
+ next;
+ }
+ #
+ # split style substitutions
+ #
+ $old = '';
+ while ($old ne $_) {
+ $old = $_;
+ if (/\@(\w+)\{/) {
+ ($before, $style, $after) = ($`, $1, $');
+ if (defined($style_map{$style})) {
+ $_ = $after;
+ $text = '';
+ $after = '';
+ $failed = 1;
+ while (@lines2) {
+ if (/\}/) {
+ $text .= $`;
+ $after = $';
+ $failed = 0;
+ last;
+ } else {
+ $text .= $_;
+ $_ = shift(@lines2);
+ }
+ }
+ if ($failed) {
+ die "* Bad syntax (\@$style) after: $before\n";
+ } else {
+ $text = &apply_style($style, $text);
+ $_ = "$before$text$after";
+ }
+ }
+ }
+ }
+ # otherwise
+ push(@lines3, $_);
+}
+print "# end of pass 3\n" if $verbose;
+
+#+++############################################################################
+# #
+# Pass 4: foot notes, final cleanup #
+# #
+#---############################################################################
+
+@foot_lines = (); # footnotes
+@doc_lines = (); # final document
+$end_of_para = 0; # true if last line is <P>
+
+while (@lines3)
+{
+ $_ = shift(@lines3);
+ #
+ # special case (protected sections)
+ #
+ if (/^$PROTECTTAG/o) {
+ push(@doc_lines, $_);
+ $end_of_para = 0;
+ next;
+ }
+ #
+ # footnotes
+ #
+ while (/\@footnote([^\{\s]+)\{/) {
+ ($before, $d, $after) = ($`, $1, $');
+ $_ = $after;
+ $text = '';
+ $after = '';
+ $failed = 1;
+ while (@lines3) {
+ if (/\}/) {
+ $text .= $`;
+ $after = $';
+ $failed = 0;
+ last;
+ } else {
+ $text .= $_;
+ $_ = shift(@lines3);
+ }
+ }
+ if ($failed) {
+ die "* Bad syntax (\@footnote) after: $before\n";
+ } else {
+ $foot_num++;
+ $docid = "DOCF$foot_num";
+ $footid = "FOOT$foot_num";
+ $foot = "($foot_num)";
+ push(@foot_lines, "<H3>" . &anchor($footid, "$d#$docid", $foot) . "</H3>\n");
+ $text = "<P>$text" unless $text =~ /^\s*<P>/;
+ push(@foot_lines, "$text\n");
+ $_ = $before . &anchor($docid, "$docu_foot#$footid", $foot) . $after;
+ }
+ }
+ #
+ # remove unnecessary <P>
+ #
+ if (/^\s*<P>\s*$/) {
+ next if $end_of_para++;
+ } else {
+ $end_of_para = 0;
+ }
+ # otherwise
+ push(@doc_lines, $_);
+}
+print "# end of pass 4\n" if $verbose;
+
+#+++############################################################################
+# #
+# Pass 5: print things #
+# #
+#---############################################################################
+
+$header = <<EOT;
+<!-- This HTML file has been created by $THISPROG
+ from $docu on $TODAY -->
+EOT
+
+ $full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document";
+ $title = $value{'_settitle'} || $full_title;
+ $_ = &substitute_style($full_title);
+ &unprotect_texi;
+ s/\n$//; # rmv last \n (if any)
+ $full_title = "<H1>" . join("</H1>\n<H1>", split(/\n/, $_)) . "</H1>\n";
+
+#
+# print ToC
+#
+if (!$monolithic && @toc_lines)
+{
+ if (open(FILE, "> $docu_toc")) {
+ print "# creating $docu_toc...\n" if $verbose;
+ &print_toplevel_header("$title - Table of Contents");
+ &print_ruler;
+ &print(*toc_lines, FILE);
+ &print_toplevel_footer;
+ close(FILE);
+ } else {
+ warn "$ERROR Can't write (toc) to $docu_toc: $!\n";
+ }
+}
+
+#
+# print footnotes
+#
+if (!$monolithic && @foot_lines)
+{
+ if (open(FILE, "> $docu_foot")) {
+ print "# creating $docu_foot...\n" if $verbose;
+ &print_toplevel_header("$title - Footnotes");
+ &print_ruler;
+ &print(*foot_lines, FILE);
+ &print_toplevel_footer;
+ close(FILE);
+ } else {
+ warn "$ERROR Can't write (foot) to $docu_foot: $!\n";
+ }
+}
+
+#
+# print document
+#
+
+if ($split_chapter || $split_node)
+{ # split
+ $doc_num = 0;
+ $last_num = scalar(@sections);
+ $first_doc = &doc_name(1);
+ $last_doc = &doc_name($last_num);
+ while (@sections) {
+ $section = shift(@sections);
+ &next_doc;
+ # Remove added links part
+ if (open(FILE, ">$docu_doc")) {
+ print "# creating $docu_doc... ($section)\n" if $verbose;
+ &print_header("$title - $section") unless $opt_empty_headers;
+ $prev_doc = ($doc_num == 1 ? undef : &doc_name($doc_num - 1));
+ $next_doc = ($doc_num == $last_num ? undef : &doc_name($doc_num + 1));
+ $navigation = "Go to the ";
+ $navigation .= ($prev_doc ? &anchor('', $first_doc, "first") : "first");
+ $navigation .= ", ";
+ $navigation .= ($prev_doc ? &anchor('', $prev_doc, "previous") : "previous");
+ $navigation .= ", ";
+ $navigation .= ($next_doc ? &anchor('', $next_doc, "next") : "next");
+ $navigation .= ", ";
+ $navigation .= ($next_doc ? &anchor('', $last_doc, "last") : "last");
+ $navigation .= " section, " . &anchor('', $docu_toc, "table of contents") . ".\n";
+ print FILE $navigation unless $opt_empty_headers;
+ &print_ruler unless $opt_empty_headers;
+ # find corresponding lines
+ @tmp_lines = ();
+ while (@doc_lines) {
+ $_ = shift(@doc_lines);
+ last if ($_ eq $SPLITTAG);
+ push(@tmp_lines, $_);
+ }
+ &print(*tmp_lines, FILE);
+ &print_ruler unless $opt_empty_headers;
+ print FILE $navigation unless $opt_empty_headers;
+ &print_footer unless $opt_empty_headers;
+ close(FILE);
+ } else {
+ warn "$ERROR Can't write (doc) to $docu_doc: $!\n";
+ }
+ }
+}
+else
+{ # not split
+ if (open(FILE, ">$docu_doc")) {
+ print "# creating $docu_doc...\n" if $verbose;
+ if ($monolithic || !@toc_lines) {
+ &print_toplevel_header($title);
+ } else {
+ &print_header($title);
+ print FILE $full_title;
+ }
+ if ($monolithic && @toc_lines) {
+ &print_ruler;
+ print FILE "<H1>Table of Contents</H1>\n";
+ &print(*toc_lines, FILE);
+ }
+ &print_ruler;
+ &print(*doc_lines, FILE);
+ if ($monolithic && @foot_lines) {
+ &print_ruler;
+ print FILE "<H1>Footnotes</H1>\n";
+ &print(*foot_lines, FILE);
+ }
+ if ($monolithic || !@toc_lines) {
+ &print_toplevel_footer;
+ } else {
+ &print_footer;
+ }
+ close(FILE);
+ } else {
+ warn "$ERROR Can't write (doc2) to $docu_doc: $!\n";
+ }
+}
+
+print "# that's all folks\n" if $verbose;
+
+#+++############################################################################
+# #
+# Low level functions #
+# #
+#---############################################################################
+
+sub update_sec_num
+{
+ local($name, $level) = @_;
+
+ $level--; # here we start at 0
+ if ($name =~ /^appendix/) {
+ # appendix style
+ if (defined(@appendix_sec_num)) {
+ &incr_sec_num($level, @appendix_sec_num);
+ } else {
+ @appendix_sec_num = ('A', 0, 0, 0);
+ }
+ return(join('.', @appendix_sec_num[0..$level]));
+ } else {
+ # normal style
+ if (defined(@normal_sec_num)) {
+ &incr_sec_num($level, @normal_sec_num);
+ } else {
+ @normal_sec_num = (1, 0, 0, 0);
+ }
+ return(join('.', @normal_sec_num[0..$level]));
+ }
+}
+
+sub incr_sec_num
+{
+ local($level, $l);
+ $level = shift(@_);
+ $_[$level]++;
+ foreach $l ($level+1 .. 3) {
+ $_[$l] = 0;
+ }
+}
+
+sub check
+{
+ local($_, %seen, %context, $before, $match, $after);
+
+ while (<>) {
+ if (/\@(\*|\.|\:|\@|\{|\})/) {
+ $seen{$&}++;
+ $context{$&} .= "> $_" if $verbose;
+ $_ = "$`XX$'";
+ redo;
+ }
+ if (/\@(\w+)/) {
+ ($before, $match, $after) = ($`, $&, $');
+ if ($before =~ /\b[\w-]+$/ && $after =~ /^[\w-.]*\b/) { # e-mail address
+ $seen{'e-mail address'}++;
+ $context{'e-mail address'} .= "> $_" if $verbose;
+ } else {
+ $seen{$match}++;
+ $context{$match} .= "> $_" if $verbose;
+ }
+ $match =~ s/^\s*\@/X/;
+ $_ = "$before$match$after";
+ redo;
+ }
+ }
+
+ foreach (sort(keys(%seen))) {
+ if ($verbose) {
+ print "$_\n";
+ print $context{$_};
+ } else {
+ print "$_ ($seen{$_})\n";
+ }
+ }
+}
+
+sub open
+{
+ local($name) = @_;
+
+ ++$fh_name;
+ if (open($fh_name, $name)) {
+ unshift(@fhs, $fh_name);
+ } else {
+ warn "$ERROR Can't read file $name: $!\n";
+ }
+}
+
+sub init_input
+{
+ @fhs = (); # hold the file handles to read
+ @input_spool = (); # spooled lines to read
+ $fh_name = 'FH000';
+ &open($docu);
+}
+
+sub next_line
+{
+ local($fh, $line);
+
+ if (@input_spool) {
+ $line = shift(@input_spool);
+ return($line);
+ }
+ while (@fhs) {
+ $fh = $fhs[0];
+ $line = <$fh>;
+ return($line) if $line;
+ close($fh);
+ shift(@fhs);
+ }
+ return(undef);
+}
+
+# used in pass 1, use &next_line
+sub skip_until
+{
+ local($tag) = @_;
+ local($_);
+
+ while ($_ = &next_line) {
+ return if /^\s*\@end\s+$tag\s*$/;
+ }
+ die "* Failed to find '$tag' after: " . $lines[$#lines];
+}
+
+#
+# HTML stacking to have a better HTML output
+#
+
+sub html_reset
+{
+ @html_stack = ('html');
+ $html_element = 'body';
+}
+
+sub html_push
+{
+ local($what) = @_;
+ push(@html_stack, $html_element);
+ $html_element = $what;
+}
+
+sub html_push_if
+{
+ local($what) = @_;
+ push(@html_stack, $html_element)
+ if ($html_element && $html_element ne 'P');
+ $html_element = $what;
+}
+
+sub html_pop
+{
+ $html_element = pop(@html_stack);
+}
+
+sub html_pop_if
+{
+ local($elt);
+
+ if (@_) {
+ foreach $elt (@_) {
+ if ($elt eq $html_element) {
+ $html_element = pop(@html_stack) if @html_stack;
+ last;
+ }
+ }
+ } else {
+ $html_element = pop(@html_stack) if @html_stack;
+ }
+}
+
+sub html_debug
+{
+ local($what, $line) = @_;
+ return("<!-- $line @html_stack, $html_element -->$what")
+ if $debug & $DEBUG_HTML;
+ return($what);
+}
+
+# to debug the output...
+sub debug
+{
+ local($what, $line) = @_;
+ return("<!-- $line -->$what")
+ if $debug & $DEBUG_HTML;
+ return($what);
+}
+
+sub normalise_node
+{
+ $_[0] =~ s/\s+/ /g;
+ $_[0] =~ s/ $//;
+ $_[0] =~ s/^ //;
+}
+
+sub menu_entry
+{
+ local($entry, $node, $descr) = @_;
+ local($href);
+
+ &normalise_node($node);
+ $href = $node2href{$node};
+ if ($href) {
+ $descr =~ s/^\s+//;
+ $descr = ": $descr" if $descr;
+ push(@lines2, "<LI>" . &anchor('', $href, $entry) . "$descr\n");
+ } else {
+ warn "$ERROR Undefined node ($node): $_";
+ }
+}
+
+sub do_ctrl { "^$_[0]" }
+
+sub do_sc { "\U$_[0]\E" }
+
+sub fix_image
+{
+ my($text) = @_;
+ my($arg1, $ext);
+ $text =~ /^([^,]*)$/;
+ die "error in image: '$text'" unless defined($1);
+ $arg1 = $1;
+ $arg1 =~ s/@@/@/g;
+ $ext = "jpg" if -f "$arg1.jpg";
+ $ext = "gif" if -f "$arg1.gif";
+ if (defined($ext))
+ {
+ "<IMG SRC=\"$arg1.$ext\">";
+ }
+ else
+ {
+ warn "Image $arg1 not found";
+ "";
+ }
+}
+
+sub fix_url
+{
+ my($text) = @_;
+ $text =~ s/@@/@/g;
+ $text;
+}
+
+sub fix_uref
+{
+ my($text) = @_;
+ my($arg1, $arg2);
+ $text =~ /^([^,]*),?([^,]*)?$/;
+ die "error in uref: '$text'" unless defined($1);
+ $arg1 = $1;
+ $arg2 = (defined($2) && $2) ? $2 : $arg1;
+ $arg1 =~ s/@@/@/g;
+ $arg2 =~ s/@@/@/g;
+ "<a HREF=\"$arg1\">$arg2</a>";
+}
+
+sub fix_email
+{
+ my($text) = @_;
+ my($arg1, $arg2);
+ $text =~ /^([^,]*)(,[^,]*)?$/;
+ die "error in email: '$text'" unless defined($1);
+ $arg1 = $1;
+ $arg2 = defined($2) ? $2 : $arg1;
+ $arg1 =~ s/@@/@/g;
+ $arg2 =~ s/@@/@/g;
+ "<a HREF=\"mailto:$arg1\">$arg2</a>";
+}
+
+sub apply_style
+{
+ local($texi_style, $text) = @_;
+ local($style);
+
+ $style = $style_map{$texi_style};
+ if (defined($style)) { # known style
+ if ($style =~ /^\"/) { # add quotes
+ $style = $';
+ $text = "\`$text\'";
+ }
+ if ($style =~ /^\&/) { # custom
+ $style = $';
+ $text = &$style($text);
+ } elsif ($style) { # good style
+ $text = "<$style>$text</$style>";
+ } else { # no style
+ }
+ } else { # unknown style
+ $text = undef;
+ }
+ return($text);
+}
+
+# remove Texinfo styles
+sub remove_style
+{
+ local($_) = @_;
+ s/\@\w+{([^\{\}]+)}/$1/g;
+ return($_);
+}
+
+sub substitute_style
+{
+ local($_) = @_;
+ local($changed, $done, $style, $text);
+
+ $changed = 1;
+ while ($changed) {
+ $changed = 0;
+ $done = '';
+ while (/\@(\w+){([^\{\}]+)}/) {
+ $text = &apply_style($1, $2);
+ if ($text) {
+ $_ = "$`$text$'";
+ $changed = 1;
+ } else {
+ $done .= "$`\@$1";
+ $_ = "{$2}$'";
+ }
+ }
+ $_ = $done . $_;
+ }
+ return($_);
+}
+
+sub anchor
+{
+ local($name, $href, $text, $newline) = @_;
+ local($result);
+
+ $result = "<A";
+ $result .= " NAME=\"$name\"" if $name;
+ $result .= " HREF=\"$href\"" if $href;
+ $result .= ">$text</A>";
+ $result .= "\n" if $newline;
+ return($result);
+}
+
+sub pretty_date
+{
+ local(@MoY, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
+
+ @MoY = ('January', 'Febuary', 'March', 'April', 'May', 'June',
+ 'July', 'August', 'September', 'October', 'November', 'December');
+ ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
+ $year += ($year < 70) ? 2000 : 1900;
+ return("$mday $MoY[$mon] $year");
+}
+
+sub doc_name
+{
+ local($num) = @_;
+ my($real_name, $link_name);
+ $real_name = ($opt_use_numbers) ? $num : $doc_node_name[$num];
+ $link_name = ($opt_special_links) ?
+ $doc_node_name_links[$num] : $real_name;
+ # print "# num $num osl $opt_special_links link $link_name\n";
+ return("${docu_name}_$real_name.html",
+ "$opt_special_links${docu_name}_$link_name.html");
+}
+
+sub next_doc
+{
+ ($docu_doc, $link_doc) = &doc_name(++$doc_num);
+}
+
+sub print
+{
+ local(*lines, $fh) = @_;
+ local($_);
+
+ while (@lines) {
+ $_ = shift(@lines);
+ if (/^$PROTECTTAG/o) {
+ $_ = $tag2pro{$_};
+ } else {
+ &unprotect_texi;
+ }
+ print $fh $_;
+ }
+}
+
+sub print_ruler
+{
+ print FILE "<P><HR><P>\n";
+}
+
+sub print_header
+{
+ local($_);
+
+ # clean the title
+ $_ = &remove_style($_[0]);
+ &unprotect_texi;
+ # print the header
+ if ($doctype eq 'html2') {
+ print FILE $html2_doctype;
+ } elsif ($doctype) {
+ print FILE $doctype;
+ }
+ my($tags) = defined($value{"_body_tags"}) ? " " . $value{"_body_tags"} : "";
+ my($et) = defined($value{"_extra_head"}) ? " " . $value{"_extra_head"} : "";
+ $et = &unprotect_html($et);
+ print FILE <<EOT;
+ <HTML>
+ <HEAD>
+ $header
+ <TITLE>$_</TITLE>
+ $et
+ </HEAD>
+ <BODY$tags>
+EOT
+}
+
+sub print_toplevel_header
+{
+ local($_);
+
+ &print_header; # pass given arg...
+ print FILE $full_title;
+ if ($value{'_subtitle'}) {
+ $value{'_subtitle'} =~ s/\n+$//;
+ foreach (split(/\n/, $value{'_subtitle'})) {
+ $_ = &substitute_style($_);
+ &unprotect_texi;
+ print FILE "<H2>$_</H2>\n";
+ }
+ }
+ if ($value{'_author'}) {
+ $value{'_author'} =~ s/\n+$//;
+ foreach (split(/\n/, $value{'_author'})) {
+ $_ = &substitute_style($_);
+ &unprotect_texi;
+ s/[\w.-]+\@[\w.-]+/<A HREF="mailto:$&">$&<\/A>/g;
+ print FILE "<ADDRESS>$_</ADDRESS>\n";
+ }
+ }
+ print FILE "<P>\n";
+}
+
+sub print_footer
+{
+ print FILE <<EOT;
+ </BODY>
+ </HTML>
+EOT
+}
+
+sub print_toplevel_footer
+{
+ &print_ruler;
+ print FILE <<EOT;
+This document was generated on $TODAY using the
+<A HREF=\"$HOMEPAGE\">texi2html</A>
+translator version 1.52 (extended by davida\@detron.se).</P>
+EOT
+ &print_footer;
+}
+
+sub protect_texi
+{
+ # protect @ { } ` '
+ s/\@\@/$;0/go;
+ s/\@\{/$;1/go;
+ s/\@\}/$;2/go;
+ s/\@\`/$;3/go;
+ s/\@\'/$;4/go;
+}
+
+sub protect_html
+{
+ local($what) = @_;
+ # protect & < >
+ # Avoid loop in & replacement. This instead bugs out for &# in text..
+ $what =~ s/\&([^#]|$)/\&\#38;$1/g;
+ $what =~ s/\</\&\#60;/g;
+ $what =~ s/\>/\&\#62;/g;
+ # but recognize some HTML things
+ $what =~ s/\&\#60;\/A\&\#62;/<\/A>/g; # </A>
+ $what =~ s/\&\#60;A ([^\&]+)\&\#62;/<A $1>/g; # <A [^&]+>
+ $what =~ s/\&\#60;IMG ([^\&]+)\&\#62;/<IMG $1>/g; # <IMG [^&]+>
+ return($what);
+}
+
+sub unprotect_texi
+{
+ s/$;0/\@/go;
+ s/$;1/\{/go;
+ s/$;2/\}/go;
+ s/$;3/\`/go;
+ s/$;4/\'/go;
+}
+
+sub unprotect_html
+{
+ local($what) = @_;
+ $what =~ s/\&\#38;/\&/g;
+ $what =~ s/\&\#60;/\</g;
+ $what =~ s/\&\#62;/\>/g;
+ return($what);
+}
+
+sub byalpha
+{
+ $key2alpha{$a} cmp $key2alpha{$b};
+}
+
+##############################################################################
+
+ # These next few lines are legal in both Perl and nroff.
+
+ .00 ; # finish .ig
+
+ 'di \" finish diversion--previous line must be blank
+.nr nl 0-1 \" fake up transition to first page again
+.nr % 0 \" start at page 1
+'; __END__ ############# From here on it's a standard manual page ############
+.TH TEXI2HTML 1 "09/10/96"
+.AT 3
+.SH NAME
+texi2html \- a Texinfo to HTML converter
+.SH SYNOPSIS
+.B texi2html [options] file
+.PP
+.B texi2html -check [-verbose] files
+.SH DESCRIPTION
+.I Texi2html
+converts the given Texinfo file to a set of HTML files. It tries to handle
+most of the Texinfo commands. It creates hypertext links for cross-references,
+footnotes...
+.PP
+It also tries to add links from a reference to its corresponding entry in the
+bibliography (if any). It may also handle a glossary (see the
+.B \-glossary
+option).
+.PP
+.I Texi2html
+creates several files depending on the contents of the Texinfo file and on
+the chosen options (see FILES).
+.PP
+The HTML files created by
+.I texi2html
+are closer to TeX than to Info, that's why
+.I texi2html
+converts @iftex sections and not @ifinfo ones by default. You can reverse
+this with the \-expandinfo option.
+.SH OPTIONS
+.TP 12
+.B \-check
+Check the given file and give the list of all things that may be Texinfo commands.
+This may be used to check the output of
+.I texi2html
+to find the Texinfo commands that have been left in the HTML file.
+.TP
+.B \-expandinfo
+Expand @ifinfo sections, not @iftex ones.
+.TP
+.B \-glossary
+Use the section named 'Glossary' to build a list of terms and put links in the HTML
+document from each term toward its definition.
+.TP
+.B \-invisible \fIname\fP
+Use \fIname\fP to create invisible destination anchors for index links. This is a workaround
+for a known bug of many WWW browsers, including xmosaic.
+.TP
+.B \-I \fIdir\fP
+Look also in \fIdir\fP to find included files.
+.TP
+.B \-menu
+Show the Texinfo menus; by default they are ignored.
+.TP
+.B \-monolithic
+Output only one file, including the table of contents and footnotes.
+.TP
+.B \-number
+Number the sections.
+.TP
+.B \-split_chapter
+Split the output into several HTML files (one per main section:
+chapter, appendix...).
+.TP
+.B \-split_node
+Split the output into several HTML files (one per node).
+.TP
+.B \-usage
+Print usage instructions, listing the current available command-line options.
+.TP
+.B \-verbose
+Give a verbose output. Can be used with the
+.B \-check
+option.
+.PP
+.SH FILES
+By default
+.I texi2html
+creates the following files (foo being the name of the Texinfo file):
+.TP 16
+.B foo_toc.html
+The table of contents.
+.TP
+.B foo.html
+The document's contents.
+.TP
+.B foo_foot.html
+The footnotes (if any).
+.PP
+When used with the
+.B \-split
+option, it creates several files (one per chapter or node), named
+.B foo_n.html
+(n being the indice of the chapter or node), instead of the single
+.B foo.html
+file.
+.PP
+When used with the
+.B \-monolithic
+option, it creates only one file:
+.B foo.html
+.SH VARIABLES
+.I texi2html
+predefines the following variables: \fBhtml\fP, \fBtexi2html\fP.
+.SH ADDITIONAL COMMANDS
+.I texi2html
+implements the following non-Texinfo commands:
+.TP 16
+.B @ifhtml
+This indicates the start of an HTML section, this section will passed through
+without any modofication.
+.TP
+.B @end ifhtml
+This indcates the end of an HTML section.
+.SH VERSION
+This is \fItexi2html\fP version 1.52, 09/10/96.
+.PP
+The latest version of \fItexi2html\fP can be found in WWW, cf. URL
+http://wwwcn.cern.ch/dci/texi2html/
+.SH AUTHOR
+The main author is Lionel Cons, CERN CN/DCI/UWS, Lionel.Cons@cern.ch.
+Many other people around the net contributed to this program.
+.SH COPYRIGHT
+This program is the intellectual property of the European
+Laboratory for Particle Physics (known as CERN). No guarantee whatsoever is
+provided by CERN. No liability whatsoever is accepted for any loss or damage
+of any kind resulting from any defect or inaccuracy in this information or
+code.
+.PP
+CERN, 1211 Geneva 23, Switzerland
+.SH "SEE ALSO"
+GNU Texinfo Documentation Format,
+HyperText Markup Language (HTML),
+World Wide Web (WWW).
+.SH BUGS
+This program does not understand all Texinfo commands (yet).
+.PP
+TeX specific commands (normally enclosed in @iftex) will be
+passed unmodified.
+.ex
diff --git a/Docs/Support/texinfo.tex b/Docs/Support/texinfo.tex
new file mode 100644
index 00000000000..7421f884d22
--- /dev/null
+++ b/Docs/Support/texinfo.tex
@@ -0,0 +1,5868 @@
+% texinfo.tex -- TeX macros to handle Texinfo files.
+%
+% Load plain if necessary, i.e., if running under initex.
+\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
+%
+\def\texinfoversion{1999-05-25.6}%
+%
+% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
+% Free Software Foundation, Inc.
+%
+% This texinfo.tex file is free software; you can redistribute it and/or
+% modify it under the terms of the GNU General Public License as
+% published by the Free Software Foundation; either version 2, or (at
+% your option) any later version.
+%
+% This texinfo.tex file is distributed in the hope that it will be
+% useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+% General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this texinfo.tex file; see the file COPYING. If not, write
+% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+% Boston, MA 02111-1307, USA.
+%
+% In other words, you are welcome to use, share and improve this program.
+% You are forbidden to forbid anyone else to use, share and improve
+% what you give them. Help stamp out software-hoarding!
+%
+% Please try the latest version of texinfo.tex before submitting bug
+% reports; you can get the latest version from:
+% ftp://ftp.gnu.org/pub/gnu/texinfo.tex
+% (and all GNU mirrors, see http://www.gnu.org/order/ftp.html)
+% ftp://tug.org/tex/texinfo.tex
+% ftp://ctan.org/macros/texinfo/texinfo.tex
+% (and all CTAN mirrors, finger ctan@ctan.org for a list).
+% /home/gd/gnu/doc/texinfo.tex on the GNU machines.
+% The texinfo.tex in any given Texinfo distribution could well be out
+% of date, so if that's what you're using, please check.
+% There is a small home page for Texinfo at http://texinfo.org/.
+%
+% Send bug reports to bug-texinfo@gnu.org. Please include including a
+% complete document in each bug report with which we can reproduce the
+% problem. Patches are, of course, greatly appreciated.
+%
+% To process a Texinfo manual with TeX, it's most reliable to use the
+% texi2dvi shell script that comes with the distribution. For a simple
+% manual foo.texi, however, you can get away with this:
+% tex foo.texi
+% texindex foo.??
+% tex foo.texi
+% tex foo.texi
+% dvips foo.dvi -o # or whatever, to process the dvi file; this makes foo.ps.
+% The extra runs of TeX get the cross-reference information correct.
+% Sometimes one run after texindex suffices, and sometimes you need more
+% than two; texi2dvi does it as many times as necessary.
+%
+% It is possible to adapt texinfo.tex for other languages. You can get
+% the existing language-specific files from ftp://ftp.gnu.org/gnu/texinfo/.
+
+\message{Loading texinfo [version \texinfoversion]:}
+
+% If in a .fmt file, print the version number
+% and turn on active characters that we couldn't do earlier because
+% they might have appeared in the input file name.
+\everyjob{\message{[Texinfo version \texinfoversion]}%
+ \catcode`+=\active \catcode`\_=\active}
+
+% Save some parts of plain tex whose names we will redefine.
+\let\ptexb=\b
+\let\ptexbullet=\bullet
+\let\ptexc=\c
+\let\ptexcomma=\,
+\let\ptexdot=\.
+\let\ptexdots=\dots
+\let\ptexend=\end
+\let\ptexequiv=\equiv
+\let\ptexexclam=\!
+\let\ptexi=\i
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexstar=\*
+\let\ptext=\t
+
+% We never want plain's outer \+ definition in Texinfo.
+% For @tex, we can use \tabalign.
+\let\+ = \relax
+
+% Get ready for pdf.
+\newif\ifpdf
+\ifx\pdfoutput\undefined\else
+ \input pdfcolor
+ \pdfoutput=1
+ \pdftrue
+\fi
+
+\message{Basics,}
+\chardef\other=12
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Set up fixed words for English if not already set.
+\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi
+\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi
+\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi
+\ifx\putwordin\undefined \gdef\putwordin{in}\fi
+\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi
+\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi
+\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi
+\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi
+\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi
+\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi
+\ifx\putwordof\undefined \gdef\putwordof{of}\fi
+\ifx\putwordon\undefined \gdef\putwordon{on}\fi
+\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi
+\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi
+\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi
+\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi
+\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi
+\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi
+\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi
+%
+\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi
+\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi
+\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi
+\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi
+\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi
+\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi
+\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi
+\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi
+\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi
+\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi
+\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi
+\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi
+%
+\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi
+\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi
+\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi
+\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi
+\ifx\putwordDeftypevar\undefined\gdef\putwordDeftypevar{Variable}\fi
+\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi
+\ifx\putwordDeftypefun\undefined\gdef\putwordDeftypefun{Function}\fi
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+\hyphenation{white-space}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset
+\newdimen \normaloffset
+\newdimen\pagewidth \newdimen\pageheight
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal. We don't just call \tracingall here,
+% since that produces some useless output on the terminal.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\ifx\eTeXversion\undefined
+\def\loggingall{\tracingcommands2 \tracingstats2
+ \tracingpages1 \tracingoutput1 \tracinglostchars1
+ \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+\else
+\def\loggingall{\tracingcommands3 \tracingstats2
+ \tracingpages1 \tracingoutput1 \tracinglostchars1
+ \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+ \tracingscantokens1 \tracingassigns1 \tracingifs1
+ \tracinggroups1 \tracingnesting2
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+\fi
+
+% For @cropmarks command.
+% Do @cropmarks to get crop marks.
+%
+\newif\ifcropmarks
+\let\cropmarks = \cropmarkstrue
+%
+% Dimensions to add cropmarks at corners.
+% Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines
+\newdimen\cornerlong \cornerlong=1pc
+\newdimen\cornerthick \cornerthick=.3pt
+\newdimen\topandbottommargin \topandbottommargin=.75in
+
+% Main output routine.
+\chardef\PAGE = 255
+\output = {\onepageout{\pagecontents\PAGE}}
+
+\newbox\headlinebox
+\newbox\footlinebox
+
+% \onepageout takes a vbox as an argument. Note that \pagecontents
+% does insertions, but you have to call it yourself.
+\def\onepageout#1{%
+ \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi
+ %
+ \ifodd\pageno \advance\hoffset by \bindingoffset
+ \else \advance\hoffset by -\bindingoffset\fi
+ %
+ % Do this outside of the \shipout so @code etc. will be expanded in
+ % the headline as they should be, not taken literally (outputting ''code).
+ \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
+ \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}%
+ %
+ {%
+ % Have to do this stuff outside the \shipout because we want it to
+ % take effect in \write's, yet the group defined by the \vbox ends
+ % before the \shipout runs.
+ %
+ \escapechar = `\\ % use backslash in output files.
+ \indexdummies % don't expand commands in the output.
+ \normalturnoffactive % \ in index entries must not stay \, e.g., if
+ % the page break happens to be in the middle of an example.
+ \shipout\vbox{%
+ \ifcropmarks \vbox to \outervsize\bgroup
+ \hsize = \outerhsize
+ \vskip-\topandbottommargin
+ \vtop to0pt{%
+ \line{\ewtop\hfil\ewtop}%
+ \nointerlineskip
+ \line{%
+ \vbox{\moveleft\cornerthick\nstop}%
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}%
+ }%
+ \vss}%
+ \vskip\topandbottommargin
+ \line\bgroup
+ \hfil % center the page within the outer (page) hsize.
+ \ifodd\pageno\hskip\bindingoffset\fi
+ \vbox\bgroup
+ \fi
+ %
+ \unvbox\headlinebox
+ \pagebody{#1}%
+ \ifdim\ht\footlinebox > 0pt
+ % Only leave this space if the footline is nonempty.
+ % (We lessened \vsize for it in \oddfootingxxx.)
+ % The \baselineskip=24pt in plain's \makefootline has no effect.
+ \vskip 2\baselineskip
+ \unvbox\footlinebox
+ \fi
+ %
+ \ifpdf\pdfmkdest{\the\pageno}\fi
+ %
+ \ifcropmarks
+ \egroup % end of \vbox\bgroup
+ \hfil\egroup % end of (centering) \line\bgroup
+ \vskip\topandbottommargin plus1fill minus1fill
+ \boxmaxdepth = \cornerthick
+ \vbox to0pt{\vss
+ \line{%
+ \vbox{\moveleft\cornerthick\nsbot}%
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}%
+ }%
+ \nointerlineskip
+ \line{\ewbot\hfil\ewbot}%
+ }%
+ \egroup % \vbox from first cropmarks clause
+ \fi
+ }% end of \shipout\vbox
+ }% end of group with \turnoffactive
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi
+}
+
+\newinsert\margin \dimen\margin=\maxdimen
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+% marginal hacks, juha@viisa.uucp (Juha Takala)
+\ifvoid\margin\else % marginal info is present
+ \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+% Here are the rules for the cropmarks. Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+ {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+ {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1. The argument is the rest of
+% the input line (except we remove a trailing comment). #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg#1{%
+ \let\next = #1%
+ \begingroup
+ \obeylines
+ \futurelet\temp\parseargx
+}
+
+% If the next token is an obeyed space (from an @example environment or
+% the like), remove it and recurse. Otherwise, we're done.
+\def\parseargx{%
+ % \obeyedspace is defined far below, after the definition of \sepspaces.
+ \ifx\obeyedspace\temp
+ \expandafter\parseargdiscardspace
+ \else
+ \expandafter\parseargline
+ \fi
+}
+
+% Remove a single space (as the delimiter token to the macro call).
+{\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+{\obeylines %
+ \gdef\parseargline#1^^M{%
+ \endgroup % End of the group started in \parsearg.
+ %
+ % First remove any @c comment, then any @comment.
+ % Result of each macro is put in \toks0.
+ \argremovec #1\c\relax %
+ \expandafter\argremovecomment \the\toks0 \comment\relax %
+ %
+ % Call the caller's macro, saved as \next in \parsearg.
+ \expandafter\next\expandafter{\the\toks0}%
+ }%
+}
+
+% Since all \c{,omment} does is throw away the argument, we can let TeX
+% do that for us. The \relax here is matched by the \relax in the call
+% in \parseargline; it could be more or less anything, its purpose is
+% just to delimit the argument to the \c.
+\def\argremovec#1\c#2\relax{\toks0 = {#1}}
+\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+% @end itemize @c foo
+% will have two active spaces as part of the argument with the
+% `itemize'. Here we remove all active spaces from #1, and assign the
+% result to \toks0.
+%
+% This loses if there are any *other* active characters besides spaces
+% in the argument -- _ ^ +, for example -- since they get expanded.
+% Fortunately, Texinfo does not define any such commands. (If it ever
+% does, the catcode of the characters in questionwill have to be changed
+% here.) But this means we cannot call \removeactivespaces as part of
+% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+% that \parsearg gets might well have any character at all in it.
+%
+\def\removeactivespaces#1{%
+ \begingroup
+ \ignoreactivespaces
+ \edef\temp{#1}%
+ \global\toks0 = \expandafter{\temp}%
+ \endgroup
+}
+
+% Change the active space to expand to nothing.
+%
+\begingroup
+ \obeyspaces
+ \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+\endgroup
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment; press RETURN to continue}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo is the same as @foo, for now.
+\newhelp\EMsimple{Press RETURN to continue.}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+% @end foo executes the definition of \Efoo.
+%
+\def\end{\parsearg\endxxx}
+\def\endxxx #1{%
+ \removeactivespaces{#1}%
+ \edef\endthing{\the\toks0}%
+ %
+ \expandafter\ifx\csname E\endthing\endcsname\relax
+ \expandafter\ifx\csname \endthing\endcsname\relax
+ % There's no \foo, i.e., no ``environment'' foo.
+ \errhelp = \EMsimple
+ \errmessage{Undefined command `@end \endthing'}%
+ \else
+ \unmatchedenderror\endthing
+ \fi
+ \else
+ % Everything's ok; the right environment has been started.
+ \csname E\endthing\endcsname
+ \fi
+}
+
+% There is an environment #1, but it hasn't been started. Give an error.
+%
+\def\unmatchedenderror#1{%
+ \errhelp = \EMsimple
+ \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+}
+
+% Define the control sequence \E#1 to give an unmatched @end error.
+%
+\def\defineunmatchedend#1{%
+ \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+}
+
+
+% Single-spacing is done by various environments (specifically, in
+% \nonfillstart and \quotations).
+\newskip\singlespaceskip \singlespaceskip = 12.5pt
+\def\singlespace{%
+ % Why was this kern here? It messes up equalizing space above and below
+ % environments. --karl, 6may93
+ %{\advance \baselineskip by -\singlespaceskip
+ %\kern \baselineskip}%
+ \setleading \singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt\char64}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+\def\mylbrace {{\tt\char123}}
+\def\myrbrace {{\tt\char125}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+\begingroup
+ % Definitions to produce actual \{ & \} command in an index.
+ \catcode`\{ = 12 \catcode`\} = 12
+ \catcode`\[ = 1 \catcode`\] = 2
+ \catcode`\@ = 0 \catcode`\\ = 12
+ @gdef@lbracecmd[\{]%
+ @gdef@rbracecmd[\}]%
+@endgroup
+
+% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
+% Others are defined by plain TeX: @` @' @" @^ @~ @= @v @H.
+\let\, = \c
+\let\dotaccent = \.
+\def\ringaccent#1{{\accent23 #1}}
+\let\tieaccent = \t
+\let\ubaraccent = \b
+\let\udotaccent = \d
+
+% Other special characters: @questiondown @exclamdown
+% Plain TeX defines: @AA @AE @O @OE @L (and lowercase versions) @ss.
+\def\questiondown{?`}
+\def\exclamdown{!`}
+
+% Dotless i and dotless j, used for accents.
+\def\imacro{i}
+\def\jmacro{j}
+\def\dotless#1{%
+ \def\temp{#1}%
+ \ifx\temp\imacro \ptexi
+ \else\ifx\temp\jmacro \j
+ \else \errmessage{@dotless can be used only with i or j}%
+ \fi\fi
+}
+
+% Be sure we're in horizontal mode when doing a tie, since we make space
+% equivalent to this in @example-like environments. Otherwise, a space
+% at the beginning of a line will start with \penalty -- and
+% since \penalty is valid in vertical mode, we'd end up putting the
+% penalty on the vertical list instead of in the new paragraph.
+{\catcode`@ = 11
+ % Avoid using \@M directly, because that causes trouble
+ % if the definition is written into an index file.
+ \global\let\tiepenalty = \@M
+ \gdef\tie{\leavevmode\penalty\tiepenalty\ }
+}
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @! is an end-of-sentence bang.
+\def\!{!\spacefactor=3000 }
+
+% @? is an end-of-sentence query.
+\def\?{?\spacefactor=3000 }
+
+% @w prevents a word break. Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox. We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line. According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0). If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+\def\group{\begingroup
+ \ifnum\catcode13=\active \else
+ \errhelp = \groupinvalidhelp
+ \errmessage{@group invalid in context where filling is enabled}%
+ \fi
+ %
+ % The \vtop we start below produces a box with normal height and large
+ % depth; thus, TeX puts \baselineskip glue before it, and (when the
+ % next line of text is done) \lineskip glue after it. (See p.82 of
+ % the TeXbook.) Thus, space below is not quite equal to space
+ % above. But it's pretty close.
+ \def\Egroup{%
+ \egroup % End the \vtop.
+ \endgroup % End the \group.
+ }%
+ %
+ \vtop\bgroup
+ % We have to put a strut on the last line in case the @group is in
+ % the midst of an example, rather than completely enclosing it.
+ % Otherwise, the interline space between the last line of the group
+ % and the first line afterwards is too small. But we can't put the
+ % strut in \Egroup, since there it would be on a line by itself.
+ % Hence this just inserts a strut at the beginning of each line.
+ \everypar = {\strut}%
+ %
+ % Since we have a strut on every line, we don't need any of TeX's
+ % normal interline spacing.
+ \offinterlineskip
+ %
+ % OK, but now we have to do something about blank
+ % lines in the input in @example-like environments, which normally
+ % just turn into \lisppar, which will insert no space now that we've
+ % turned off the interline space. Simplest is to make them be an
+ % empty paragraph.
+ \ifx\par\lisppar
+ \edef\par{\leavevmode \par}%
+ %
+ % Reset ^^M's definition to new definition of \par.
+ \obeylines
+ \fi
+ %
+ % Do @comment since we are called inside an environment such as
+ % @example, where each end-of-line in the input causes an
+ % end-of-line in the output. We don't want the end-of-line after
+ % the `@group' to put extra space in the output. Since @group
+ % should appear on a line by itself (according to the Texinfo
+ % manual), we don't worry about eating any user text.
+ \comment
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil \mil=0.001in
+
+\def\need{\parsearg\needx}
+
+% Old definition--didn't work.
+%\def\needx #1{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak
+%\prevdepth=-1000pt
+%}}
+
+\def\needx#1{%
+ % Go into vertical mode, so we don't make a big box in the middle of a
+ % paragraph.
+ \par
+ %
+ % Don't add any leading before our big empty box, but allow a page
+ % break, since the best break might be right here.
+ \allowbreak
+ \nointerlineskip
+ \vtop to #1\mil{\vfil}%
+ %
+ % TeX does not even consider page breaks if a penalty added to the
+ % main vertical list is 10000 or more. But in order to see if the
+ % empty box we just added fits on the page, we must make it consider
+ % page breaks. On the other hand, we don't want to actually break the
+ % page after the empty box. So we use a penalty of 9999.
+ %
+ % There is an extremely small chance that TeX will actually break the
+ % page at this \penalty, if there are no other feasible breakpoints in
+ % sight. (If the user is using lots of big @group commands, which
+ % almost-but-not-quite fill up a page, TeX will have a hard time doing
+ % good page breaking, for example.) However, I could not construct an
+ % example where a page broke at this \penalty; if it happens in a real
+ % document, then we can reconsider our strategy.
+ \penalty9999
+ %
+ % Back up by the size of the box, whether we did a page break or not.
+ \kern -#1\mil
+ %
+ % Do not allow a page break right after this kern.
+ \nobreak
+}
+
+% @br forces paragraph break
+
+\let\br = \par
+
+% @dots{} output an ellipsis using the current font.
+% We do .5em per period so that it has the same spacing in a typewriter
+% font as three actual period characters.
+%
+\def\dots{%
+ \leavevmode
+ \hbox to 1.5em{%
+ \hskip 0pt plus 0.25fil minus 0.25fil
+ .\hss.\hss.%
+ \hskip 0pt plus 0.5fil minus 0.5fil
+ }%
+}
+
+% @enddots{} is an end-of-sentence ellipsis.
+%
+\def\enddots{%
+ \leavevmode
+ \hbox to 2em{%
+ \hskip 0pt plus 0.25fil minus 0.25fil
+ .\hss.\hss.\hss.%
+ \hskip 0pt plus 0.5fil minus 0.5fil
+ }%
+ \spacefactor=3000
+}
+
+
+% @page forces the start of a new page
+%
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\def\exdent{\parsearg\exdentyyy}
+\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+% This defn is used inside nofill environments such as @example.
+\def\nofillexdent{\parsearg\nofillexdentyyy}
+\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+\leftline{\hskip\leftskip{\rm#1}}}}
+
+% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph.
+
+\def\inmargin#1{%
+\strut\vadjust{\nobreak\kern-\strutdepth
+ \vtop to \strutdepth{\baselineskip\strutdepth\vss
+ \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}}
+\newskip\inmarginspacing \inmarginspacing=1cm
+\def\strutdepth{\dp\strutbox}
+
+%\hbox{{\rm#1}}\hfil\break}}
+
+% @include file insert text of that file as input.
+% Allow normal characters that we make active in the argument (a file name).
+\def\include{\begingroup
+ \catcode`\\=12
+ \catcode`~=12
+ \catcode`^=12
+ \catcode`_=12
+ \catcode`|=12
+ \catcode`<=12
+ \catcode`>=12
+ \catcode`+=12
+ \parsearg\includezzz}
+% Restore active chars for included file.
+\def\includezzz#1{\endgroup\begingroup
+ % Read the included file in a group so nested @include's work.
+ \def\thisfile{#1}%
+ \input\thisfile
+\endgroup}
+
+\def\thisfile{}
+
+% @center line outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore is another way to write a comment
+
+\def\comment{\begingroup \catcode`\^^M=\other%
+\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other%
+\commentxxx}
+{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}}
+
+\let\c=\comment
+
+% @paragraphindent NCHARS
+% We'll use ems for NCHARS, close enough.
+% We cannot implement @paragraphindent asis, though.
+%
+\def\asisword{asis} % no translation, these are keywords
+\def\noneword{none}
+%
+\def\paragraphindent{\parsearg\doparagraphindent}
+\def\doparagraphindent#1{%
+ \def\temp{#1}%
+ \ifx\temp\asisword
+ \else
+ \ifx\temp\noneword
+ \defaultparindent = 0pt
+ \else
+ \defaultparindent = #1em
+ \fi
+ \fi
+ \parindent = \defaultparindent
+}
+
+% @exampleindent NCHARS
+% We'll use ems for NCHARS like @paragraphindent.
+% It seems @exampleindent asis isn't necessary, but
+% I preserve it to make it similar to @paragraphindent.
+\def\exampleindent{\parsearg\doexampleindent}
+\def\doexampleindent#1{%
+ \def\temp{#1}%
+ \ifx\temp\asisword
+ \else
+ \ifx\temp\noneword
+ \lispnarrowing = 0pt
+ \else
+ \lispnarrowing = #1em
+ \fi
+ \fi
+}
+
+% @asis just yields its argument. Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written. Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo). So we must use a
+% control sequence to switch into and out of math mode.
+%
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+%
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{\implicitmath\ptexbullet\implicitmath}
+\def\minus{\implicitmath-\implicitmath}
+
+% @refill is a no-op.
+\let\refill=\relax
+
+% If working on a large document in chapters, it is convenient to
+% be able to disable indexing, cross-referencing, and contents, for test runs.
+% This is done with @novalidate (before @setfilename).
+%
+\newif\iflinks \linkstrue % by default we want the aux files.
+\let\novalidate = \linksfalse
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+ \iflinks
+ \readauxfile
+ \fi % \openindices needs to do some work in any case.
+ \openindices
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+ %
+ % If texinfo.cnf is present on the system, read it.
+ % Useful for site-wide @afourpaper, etc.
+ % Just to be on the safe side, close the input stream before the \input.
+ \openin 1 texinfo.cnf
+ \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi
+ \closein1
+ \temp
+ %
+ \comment % Ignore the actual filename.
+}
+
+% Called from \setfilename.
+%
+\def\openindices{%
+ \newindex{cp}%
+ \newcodeindex{fn}%
+ \newcodeindex{vr}%
+ \newcodeindex{tp}%
+ \newcodeindex{ky}%
+ \newcodeindex{pg}%
+}
+
+% @bye.
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+
+\message{pdf,}
+% adobe `portable' document format
+
+\newcount\tempnum
+\newcount\lnkcount
+\newtoks\filename
+\newcount\filenamelength
+\newcount\pgn
+
+\ifpdf
+\def\pdfmkdest#1{\pdfdest name{#1@} xyz}
+\def\pdfmkpgn#1{#1@}
+
+% Adding outlines to PDF; macros for calculating structure of outlines
+% come from Petr Olsak
+\def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0%
+ \else \csname#1\endcsname \fi}
+\def\advancenumber#1{\tempnum=\expnumber{#1}\relax
+ \advance\tempnum by1
+ \expandafter\xdef\csname#1\endcsname{\the\tempnum}}
+\def\pdfmakeoutlines{{%
+ \openin 1 \jobname.toc
+ \ifeof 1\else\bgroup
+ \closein 1
+ \def\code##1{##1}
+ \def\file##1{##1}
+ \def\TeX##1{TeX}
+ \def\tt{}
+ \def\char{char}
+ \def\samp##1{##1}
+ \def\kbd##1{##1}
+ \def\key##1{##1}
+ \def\rawbackslashxx{\string\\}
+ \def\chapentry ##1##2##3{}
+ \def\unnumbchapentry ##1##2{}
+ \def\secentry ##1##2##3##4{\advancenumber{chap##2}}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{\advancenumber{sec##2.##3}}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{\advancenumber{subsec##2.##3.##4}}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \input \jobname.toc
+ \def\chapentry ##1##2##3{%
+ \pdfoutline goto name{\pdfmkpgn{##3}}count-\expnumber{chap##2}{##1}}
+ \def\unnumbchapentry ##1##2{%
+ \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
+ \def\secentry ##1##2##3##4{%
+ \pdfoutline goto name{\pdfmkpgn{##4}}count-\expnumber{sec##2.##3}{##1}}
+ \def\unnumbsecentry ##1##2{%
+ \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
+ \def\subsecentry ##1##2##3##4##5{%
+ \pdfoutline goto name{\pdfmkpgn{##5}}count-\expnumber{subsec##2.##3.##4}{##1}}
+ \def\unnumbsubsecentry ##1##2{%
+ \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
+ \def\subsubsecentry ##1##2##3##4##5##6{%
+ \pdfoutline goto name{\pdfmkpgn{##6}}{##1}}
+ \def\unnumbsubsubsecentry ##1##2{%
+ \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
+ \input \jobname.toc
+ \egroup\fi
+}}
+\pdfmakeoutlines
+
+\def\makelinks #1,{%
+ \def\params{#1}\def\E{END}%
+ \ifx\params\E
+ \let\nextmakelinks=\relax
+ \else
+ \let\nextmakelinks=\makelinks
+ \ifnum\lnkcount>0,\fi
+ \picknum{#1}%
+ \Blue\pdfannotlink attr{/Border [0 0 0]}
+ goto name{\pdfmkpgn{\the\pgn}}%
+ #1%
+ \advance\lnkcount by 1%
+ \Black\pdfendlink
+ \fi
+ \nextmakelinks
+}
+
+\def\picknum#1{\expandafter\pn#1}
+\def\pn#1{%
+ \def\p{#1}%
+ \ifx\p\lbrace
+ \let\nextpn=\ppn
+ \else
+ \let\nextpn=\ppnn
+ \def\first{#1}
+ \fi
+ \nextpn
+}
+\def\ppn#1{\pgn=#1\gobble}
+\def\ppnn{\pgn=\first}
+\def\pdfmklnk#1{\lnkcount=0\makelinks #1,END,}
+
+\def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
+\def\skipspaces#1{\def\PP{#1}\def\D{|}%
+ \ifx\PP\D\let\nextsp\relax
+ \else\let\nextsp\skipspaces
+ \ifx\p\space\else\addtokens{\filename}{\PP}%
+ \advance\filenamelength by 1
+ \fi
+ \fi
+ \nextsp}
+\def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax}
+
+\def\pdflink#1{%
+ \leavevmode\Red
+ \begingroup
+ \normalturnoffactive\def\@{@}%
+ \pdfannotlink
+ attr{/Border [0 0 0]}%
+ user{/Subtype /Link /A << /S /URI /URI (#1) >>}%
+ \endgroup
+}
+
+\else
+\let\pdflink = \gobble
+\fi % end \ifpdf
+
+\message{fonts,}
+% Font-change commands.
+
+% Texinfo sort of supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+% We don't need math for this one.
+\def\ttsl{\tenttsl}
+
+% Use Computer Modern fonts at \magstephalf (11pt).
+\newcount\mainmagstep
+\mainmagstep=\magstephalf
+
+% Set the font macro #1 to the font named #2, adding on the
+% specified font prefix (normally `cm').
+% #3 is the font's design size, #4 is a scale factor
+\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4}
+
+% Use cm as the default font prefix.
+% To specify the font prefix, you must define \fontprefix
+% before you read in texinfo.tex.
+\ifx\fontprefix\undefined
+\def\fontprefix{cm}
+\fi
+% Support font families that don't use the same naming scheme as CM.
+\def\rmshape{r}
+\def\rmbshape{bx} %where the normal face is bold
+\def\bfshape{b}
+\def\bxshape{bx}
+\def\ttshape{tt}
+\def\ttbshape{tt}
+\def\ttslshape{sltt}
+\def\itshape{ti}
+\def\itbshape{bxti}
+\def\slshape{sl}
+\def\slbshape{bxsl}
+\def\sfshape{ss}
+\def\sfbshape{ss}
+\def\scshape{csc}
+\def\scbshape{csc}
+
+\ifx\bigger\relax
+\let\mainmagstep=\magstep1
+\setfont\textrm\rmshape{12}{1000}
+\setfont\texttt\ttshape{12}{1000}
+\else
+\setfont\textrm\rmshape{10}{\mainmagstep}
+\setfont\texttt\ttshape{10}{\mainmagstep}
+\fi
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\setfont\textbf\bfshape{10}{\mainmagstep}
+\setfont\textit\itshape{10}{\mainmagstep}
+\setfont\textsl\slshape{10}{\mainmagstep}
+\setfont\textsf\sfshape{10}{\mainmagstep}
+\setfont\textsc\scshape{10}{\mainmagstep}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun, etc.
+\setfont\defbf\bxshape{10}{\magstep1} %was 1314
+\setfont\deftt\ttshape{10}{\magstep1}
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+% Fonts for indices and small examples (9pt).
+% We actually use the slanted font rather than the italic,
+% because texinfo normally uses the slanted fonts for that.
+% Do not make many font distinctions in general in the index, since they
+% aren't very useful.
+\setfont\ninett\ttshape{9}{1000}
+\setfont\ninettsl\ttslshape{10}{900}
+\setfont\indrm\rmshape{9}{1000}
+\setfont\indit\itshape{9}{1000}
+\setfont\indsl\slshape{9}{1000}
+\let\indtt=\ninett
+\let\indttsl=\ninettsl
+\let\indsf=\indrm
+\let\indbf=\indrm
+\setfont\indsc\scshape{10}{900}
+\font\indi=cmmi9
+\font\indsy=cmsy9
+
+% Fonts for title page:
+\setfont\titlerm\rmbshape{12}{\magstep3}
+\setfont\titleit\itbshape{10}{\magstep4}
+\setfont\titlesl\slbshape{10}{\magstep4}
+\setfont\titlett\ttbshape{12}{\magstep3}
+\setfont\titlettsl\ttslshape{10}{\magstep4}
+\setfont\titlesf\sfbshape{17}{\magstep1}
+\let\titlebf=\titlerm
+\setfont\titlesc\scbshape{10}{\magstep4}
+\font\titlei=cmmi12 scaled \magstep3
+\font\titlesy=cmsy10 scaled \magstep4
+\def\authorrm{\secrm}
+
+% Chapter (and unnumbered) fonts (17.28pt).
+\setfont\chaprm\rmbshape{12}{\magstep2}
+\setfont\chapit\itbshape{10}{\magstep3}
+\setfont\chapsl\slbshape{10}{\magstep3}
+\setfont\chaptt\ttbshape{12}{\magstep2}
+\setfont\chapttsl\ttslshape{10}{\magstep3}
+\setfont\chapsf\sfbshape{17}{1000}
+\let\chapbf=\chaprm
+\setfont\chapsc\scbshape{10}{\magstep3}
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+% Section fonts (14.4pt).
+\setfont\secrm\rmbshape{12}{\magstep1}
+\setfont\secit\itbshape{10}{\magstep2}
+\setfont\secsl\slbshape{10}{\magstep2}
+\setfont\sectt\ttbshape{12}{\magstep1}
+\setfont\secttsl\ttslshape{10}{\magstep2}
+\setfont\secsf\sfbshape{12}{\magstep1}
+\let\secbf\secrm
+\setfont\secsc\scbshape{10}{\magstep2}
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad.
+% \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded.
+% \setfont\ssecsl\slshape{10}{\magstep1}
+% \setfont\ssectt\ttshape{10}{\magstep1}
+% \setfont\ssecsf\sfshape{10}{\magstep1}
+
+%\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx.
+%\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than
+%\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1.
+%\setfont\ssectt\ttshape{10}{1315}
+%\setfont\ssecsf\sfshape{10}{1315}
+
+%\let\ssecbf=\ssecrm
+
+% Subsection fonts (13.15pt).
+\setfont\ssecrm\rmbshape{12}{\magstephalf}
+\setfont\ssecit\itbshape{10}{1315}
+\setfont\ssecsl\slbshape{10}{1315}
+\setfont\ssectt\ttbshape{12}{\magstephalf}
+\setfont\ssecttsl\ttslshape{10}{1315}
+\setfont\ssecsf\sfbshape{12}{\magstephalf}
+\let\ssecbf\ssecrm
+\setfont\ssecsc\scbshape{10}{\magstep1}
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled 1315
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families. Since
+% texinfo doesn't allow for producing subscripts and superscripts, we
+% don't bother to reset \scriptfont and \scriptscriptfont (which would
+% also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+ \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy
+ \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf
+ \textfont\ttfam = \tentt \textfont\sffam = \tensf
+}
+
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE. We do this so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam
+% \tenbf}, for example. By redefining \tenbf, we obviate the need to
+% redefine \bf itself.
+\def\textfonts{%
+ \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+ \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+ \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl
+ \resetmathfonts}
+\def\titlefonts{%
+ \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl
+ \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc
+ \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy
+ \let\tenttsl=\titlettsl
+ \resetmathfonts \setleading{25pt}}
+\def\titlefont#1{{\titlefonts\rm #1}}
+\def\chapfonts{%
+ \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+ \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+ \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl
+ \resetmathfonts \setleading{19pt}}
+\def\secfonts{%
+ \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+ \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+ \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl
+ \resetmathfonts \setleading{16pt}}
+\def\subsecfonts{%
+ \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+ \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+ \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl
+ \resetmathfonts \setleading{15pt}}
+\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf?
+\def\indexfonts{%
+ \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
+ \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
+ \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy \let\tenttsl=\indttsl
+ \resetmathfonts \setleading{12pt}}
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts
+
+% Define these so they can be easily changed for other fonts.
+\def\angleleft{$\langle$}
+\def\angleright{$\rangle$}
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\setfont\shortcontrm\rmshape{12}{1000}
+\setfont\shortcontbf\bxshape{12}{1000}
+\setfont\shortcontsl\slshape{12}{1000}
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+\def\smartslanted#1{{\sl #1}\futurelet\next\smartitalicx}
+\def\smartitalic#1{{\it #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartslanted
+\let\dfn=\smartslanted
+\let\emph=\smartitalic
+\let\cite=\smartslanted
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph. Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+\def\t#1{%
+ {\tt \rawbackslash \frenchspacing #1}%
+ \null
+}
+\let\ttfont=\t
+\def\samp#1{`\tclose{#1}'\null}
+\setfont\smallrm\rmshape{8}{1000}
+\font\smallsy=cmsy9
+\def\key#1{{\smallrm\textfont2=\smallsy \leavevmode\hbox{%
+ \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
+ \vbox{\hrule\kern-0.4pt
+ \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
+ \kern-0.4pt\hrule}%
+ \kern-.06em\raise0.4pt\hbox{\angleright}}}}
+% The old definition, with no lozenge:
+%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+% @file, @option are the same as @samp.
+\let\file=\samp
+\let\option=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+ {%
+ % Change normal interword space to be same as for the current font.
+ \spaceskip = \fontdimen2\font
+ %
+ % Switch to typewriter.
+ \tt
+ %
+ % But `\ ' produces the large typewriter interword space.
+ \def\ {{\spaceskip = 0pt{} }}%
+ %
+ % Turn off hyphenation.
+ \nohyphenation
+ %
+ \rawbackslash
+ \frenchspacing
+ #1%
+ }%
+ \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in \code.
+% Otherwise, it is too hard to avoid overfull hboxes
+% in the Emacs manual, the Library manual, etc.
+
+% Unfortunately, TeX uses one parameter (\hyphenchar) to control
+% both hyphenation at - and hyphenation within words.
+% We must therefore turn them both off (\tclose does that)
+% and arrange explicitly to hyphenate at a dash.
+% -- rms.
+{
+ \catcode`\-=\active
+ \catcode`\_=\active
+ %
+ \global\def\code{\begingroup
+ \catcode`\-=\active \let-\codedash
+ \catcode`\_=\active \let_\codeunder
+ \codex
+ }
+ %
+ % If we end up with any active - characters when handling the index,
+ % just treat them as a normal -.
+ \global\def\indexbreaks{\catcode`\-=\active \let-\realdash}
+}
+
+\def\realdash{-}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{\ifusingtt{\normalunderscore\discretionary{}{}{}}{\_}}
+\def\codex #1{\tclose{#1}\endgroup}
+
+%\let\exp=\tclose %Was temporary
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
+% `example' (@kbd uses ttsl only inside of @example and friends),
+% or `code' (@kbd uses normal tty font always).
+\def\kbdinputstyle{\parsearg\kbdinputstylexxx}
+\def\kbdinputstylexxx#1{%
+ \def\arg{#1}%
+ \ifx\arg\worddistinct
+ \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
+ \else\ifx\arg\wordexample
+ \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}%
+ \else\ifx\arg\wordcode
+ \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}%
+ \fi\fi\fi
+}
+\def\worddistinct{distinct}
+\def\wordexample{example}
+\def\wordcode{code}
+
+% Default is kbdinputdistinct. (Too much of a hassle to call the macro,
+% the catcodes are wrong for parsearg to work.)
+\gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else{\tclose{\kbdfont\look}}\fi
+\else{\tclose{\kbdfont\look}}\fi}
+
+% For @url, @env, @command quotes seem unnecessary, so use \code.
+\let\url=\code
+\let\env=\code
+\let\command=\code
+
+% @uref (abbreviation for `urlref') takes an optional (comma-separated)
+% second argument specifying the text to display and an optional third
+% arg as text to display instead of (rather than in addition to) the url
+% itself. First (mandatory) arg is the url. Perhaps eventually put in
+% a hypertex \special here.
+%
+\def\uref#1{\douref #1,,,\finish}
+\def\douref#1,#2,#3,#4\finish{%
+ \pdflink{#1}%
+ \setbox0 = \hbox{\ignorespaces #3}%
+ \ifdim\wd0 > 0pt
+ \unhbox0 % third arg given, show only that
+ \else
+ \setbox0 = \hbox{\ignorespaces #2}%
+ \ifdim\wd0 > 0pt
+ \ifpdf
+ \unhbox0 % PDF: 2nd arg given, show only it
+ \else
+ \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url
+ \fi
+ \else
+ \code{#1}% only url given, so show it
+ \fi
+ \fi
+ %
+ \ifpdf
+ \Black\pdfendlink
+ \fi
+}
+
+% rms does not like angle brackets --karl, 17may97.
+% So now @email is just like @uref, unless we are pdf.
+%
+%\def\email#1{\angleleft{\tt #1}\angleright}
+\ifpdf
+ \def\email#1{\doemail#1,,\finish}
+ \def\doemail#1,#2,#3\finish{%
+ \pdflink{mailto:#1}%
+ \setbox0 = \hbox{\ignorespaces #2}%
+ \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi
+ \Black\pdfendlink
+ }
+\else
+ \let\email=\uref
+\fi
+
+% Check if we are currently using a typewriter font. Since all the
+% Computer Modern typewriter fonts have zero interword stretch (and
+% shrink), and it is reasonable to expect all typewriter fonts to have
+% this property, we can check that font parameter.
+%
+\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
+
+% Typeset a dimension, e.g., `in' or `pt'. The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+% @l was never documented to mean ``switch to the Lisp font'',
+% and it is not used as such in any manual I can find. We need it for
+% Polish suppressed-l. --karl, 22sep96.
+%\def\l#1{{\li #1}\null}
+
+% Explicit font changes: @r, @sc, undocumented @ii.
+\def\r#1{{\rm #1}} % roman font
+\def\sc#1{{\smallcaps#1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+% @acronym downcases the argument and prints in smallcaps.
+\def\acronym#1{{\smallcaps \lowercase{#1}}}
+
+% @pounds{} is a sterling sign.
+\def\pounds{{\it\$}}
+
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page. Must do @settitle before @titlepage.
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+% Do an implicit @contents or @shortcontents after @end titlepage if the
+% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage.
+%
+\newif\ifsetcontentsaftertitlepage
+ \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue
+\newif\ifsetshortcontentsaftertitlepage
+ \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue
+
+\def\shorttitlepage{\parsearg\shorttitlepagezzz}
+\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+ \endgroup\page\hbox{}\page}
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+ \let\subtitlerm=\tenrm
+ \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+ %
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ %
+ % Leave some space at the very top of the page.
+ \vglue\titlepagetopglue
+ %
+ % Now you can print the title using @title.
+ \def\title{\parsearg\titlezzz}%
+ \def\titlezzz##1{\leftline{\titlefonts\rm ##1}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt width \hsize \vskip4pt}%
+ % No rule at page bottom unless we print one at the top with @title.
+ \finishedtitlepagetrue
+ %
+ % Now you can put text using @subtitle.
+ \def\subtitle{\parsearg\subtitlezzz}%
+ \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+ %
+ % @author should come last, but may come many times.
+ \def\author{\parsearg\authorzzz}%
+ \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+ {\authorfont \leftline{##1}}}%
+ %
+ % Most title ``pages'' are actually two pages long, with space
+ % at the top of the second. We don't want the ragged left on the second.
+ \let\oldpage = \page
+ \def\page{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ \oldpage
+ \let\page = \oldpage
+ \hbox{}}%
+% \def\page{\oldpage \hbox{}}
+}
+
+\def\Etitlepage{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ % It is important to do the page break before ending the group,
+ % because the headline and footline are only empty inside the group.
+ % If we use the new definition of \page, we always get a blank page
+ % after the title page, which we certainly don't want.
+ \oldpage
+ \endgroup
+ %
+ % If they want short, they certainly want long too.
+ \ifsetshortcontentsaftertitlepage
+ \shortcontents
+ \contents
+ \global\let\shortcontents = \relax
+ \global\let\contents = \relax
+ \fi
+ %
+ \ifsetcontentsaftertitlepage
+ \contents
+ \global\let\contents = \relax
+ \global\let\shortcontents = \relax
+ \fi
+ %
+ \HEADINGSon
+}
+
+\def\finishtitlepage{%
+ \vskip4pt \hrule height 2pt width \hsize
+ \vskip\titlepagebottomglue
+ \finishedtitlepagetrue
+}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks\evenheadline % headline on even pages
+\newtoks\oddheadline % headline on odd pages
+\newtoks\evenfootline % footline on even pages
+\newtoks\oddfootline % footline on odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+ \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+ \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what @headings on does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+ \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}%
+ %
+ % Leave some space for the footline. Hopefully ok to assume
+ % @evenfooting will not be used by itself.
+ \global\advance\pageheight by -\baselineskip
+ \global\advance\vsize by -\baselineskip
+}
+
+\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}}
+%
+}% unbind the catcode of @.
+
+% @headings double turns headings on for double-sided printing.
+% @headings single turns headings on for single-sided printing.
+% @headings off turns them off.
+% @headings on same as @headings double, retained for compatibility.
+% @headings after turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off at the start of a document,
+% and turned `on' after @end titlepage.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+\let\contentsalignmacro = \chappager
+
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{%
+ \number\day\space
+ \ifcase\month
+ \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr
+ \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug
+ \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec
+ \fi
+ \space\number\year}
+
+% @settitle line... specifies the title of the document, for headings.
+% It generates no output of its own.
+\def\thistitle{\putwordNoTitle}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+
+\message{tables,}
+% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @vtable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\newif\ifitemxneedsnegativevskip
+
+\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi}
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\itemxpar \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\itemxpar \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+ \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+ \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+ \advance\hsize by -\rightskip
+ \advance\hsize by -\tableindent
+ \setbox0=\hbox{\itemfont{#1}}%
+ \itemindex{#1}%
+ \nobreak % This prevents a break before @itemx.
+ %
+ % If the item text does not fit in the space we have, put it on a line
+ % by itself, and do not allow a page break either before or after that
+ % line. We do not start a paragraph here because then if the next
+ % command is, e.g., @kindex, the whatsit would get put into the
+ % horizontal list on a line by itself, resulting in extra blank space.
+ \ifdim \wd0>\itemmax
+ %
+ % Make this a paragraph so we get the \parskip glue and wrapping,
+ % but leave it ragged-right.
+ \begingroup
+ \advance\leftskip by-\tableindent
+ \advance\hsize by\tableindent
+ \advance\rightskip by0pt plus1fil
+ \leavevmode\unhbox0\par
+ \endgroup
+ %
+ % We're going to be starting a paragraph, but we don't want the
+ % \parskip glue -- logically it's part of the @item we just started.
+ \nobreak \vskip-\parskip
+ %
+ % Stop a page break at the \parskip glue coming up. Unfortunately
+ % we can't prevent a possible page break at the following
+ % \baselineskip glue.
+ \nobreak
+ \endgroup
+ \itemxneedsnegativevskipfalse
+ \else
+ % The item text fits into the space. Start a paragraph, so that the
+ % following text (if any) will end up on the same line.
+ \noindent
+ % Do this with kerns and \unhbox so that if there is a footnote in
+ % the item text, it can migrate to the main vertical list and
+ % eventually be printed.
+ \nobreak\kern-\tableindent
+ \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0
+ \unhbox0
+ \nobreak\kern\dimen0
+ \endgroup
+ \itemxneedsnegativevskiptrue
+ \fi
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+% Contains a kludge to get @end[description] to work.
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+% @table, @ftable, @vtable.
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1 \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1 \endtabley
+\def\Eftable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+{\obeylines\obeyspaces%
+\gdef\vtablex #1^^M{%
+\tabley\vritemindex#1 \endtabley
+\def\Evtable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+\def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Necessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\exdentamount=\tableindent
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\afterenvbreak\endgroup}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+ \begingroup % ended by the @end itemize
+ \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\exdentamount=\itemindent
+\parindent = 0pt %
+\parskip = \smallskipamount %
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\afterenvbreak\endgroup}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+ \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list. No
+% argument is the same as `1'.
+%
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1 \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+ \begingroup % ended by the @end enumerate
+ %
+ % If we were given no argument, pretend we were given `1'.
+ \def\thearg{#1}%
+ \ifx\thearg\empty \def\thearg{1}\fi
+ %
+ % Detect if the argument is a single token. If so, it might be a
+ % letter. Otherwise, the only valid thing it can be is a number.
+ % (We will always have one token, because of the test we just made.
+ % This is a good thing, since \splitoff doesn't work given nothing at
+ % all -- the first parameter is undelimited.)
+ \expandafter\splitoff\thearg\endmark
+ \ifx\rest\empty
+ % Only one token in the argument. It could still be anything.
+ % A ``lowercase letter'' is one whose \lccode is nonzero.
+ % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+ % not equal to itself.
+ % Otherwise, we assume it's a number.
+ %
+ % We need the \relax at the end of the \ifnum lines to stop TeX from
+ % continuing to look for a <number>.
+ %
+ \ifnum\lccode\expandafter`\thearg=0\relax
+ \numericenumerate % a number (we hope)
+ \else
+ % It's a letter.
+ \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+ \lowercaseenumerate % lowercase letter
+ \else
+ \uppercaseenumerate % uppercase letter
+ \fi
+ \fi
+ \else
+ % Multiple tokens in the argument. We hope it's a number.
+ \numericenumerate
+ \fi
+}
+
+% An @enumerate whose labels are integers. The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+ \itemno = \thearg
+ \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more lowercase letters in @enumerate; get a bigger
+ alphabet}%
+ \fi
+ \char\lccode\itemno
+ }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more uppercase letters in @enumerate; get a bigger
+ alphabet}
+ \fi
+ \char\uccode\itemno
+ }%
+}
+
+% Call itemizey, adding a period to the first argument and supplying the
+% common last two arguments. Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+ \advance\itemno by -1
+ \itemizey{#1.}\Eenumerate\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{In hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+% @multitable macros
+% Amy Hendrickson, 8/18/94, 3/6/96
+%
+% @multitable ... @end multitable will make as many columns as desired.
+% Contents of each column will wrap at width given in preamble. Width
+% can be specified either with sample text given in a template line,
+% or in percent of \hsize, the current width of text on page.
+
+% Table can continue over pages but will only break between lines.
+
+% To make preamble:
+%
+% Either define widths of columns in terms of percent of \hsize:
+% @multitable @columnfractions .25 .3 .45
+% @item ...
+%
+% Numbers following @columnfractions are the percent of the total
+% current hsize to be used for each column. You may use as many
+% columns as desired.
+
+
+% Or use a template:
+% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+% @item ...
+% using the widest term desired in each column.
+%
+% For those who want to use more than one line's worth of words in
+% the preamble, break the line within one argument and it
+% will parse correctly, i.e.,
+%
+% @multitable {Column 1 template} {Column 2 template} {Column 3
+% template}
+% Not:
+% @multitable {Column 1 template} {Column 2 template}
+% {Column 3 template}
+
+% Each new table line starts with @item, each subsequent new column
+% starts with @tab. Empty columns may be produced by supplying @tab's
+% with nothing between them for as many times as empty columns are needed,
+% ie, @tab@tab@tab will produce two empty columns.
+
+% @item, @tab, @multitable or @end multitable do not need to be on their
+% own lines, but it will not hurt if they are.
+
+% Sample multitable:
+
+% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+% @item first col stuff @tab second col stuff @tab third col
+% @item
+% first col stuff
+% @tab
+% second col stuff
+% @tab
+% third col
+% @item first col stuff @tab second col stuff
+% @tab Many paragraphs of text may be used in any column.
+%
+% They will wrap at the width determined by the template.
+% @item@tab@tab This will be in third column.
+% @end multitable
+
+% Default dimensions may be reset by user.
+% @multitableparskip is vertical space between paragraphs in table.
+% @multitableparindent is paragraph indent in table.
+% @multitablecolmargin is horizontal space to be left between columns.
+% @multitablelinespace is space to leave between table items, baseline
+% to baseline.
+% 0pt means it depends on current normal line spacing.
+%
+\newskip\multitableparskip
+\newskip\multitableparindent
+\newdimen\multitablecolspace
+\newskip\multitablelinespace
+\multitableparskip=0pt
+\multitableparindent=6pt
+\multitablecolspace=12pt
+\multitablelinespace=0pt
+
+% Macros used to set up halign preamble:
+%
+\let\endsetuptable\relax
+\def\xendsetuptable{\endsetuptable}
+\let\columnfractions\relax
+\def\xcolumnfractions{\columnfractions}
+\newif\ifsetpercent
+
+% #1 is the part of the @columnfraction before the decimal point, which
+% is presumably either 0 or the empty string (but we don't check, we
+% just throw it away). #2 is the decimal part, which we use as the
+% percent of \hsize for this column.
+\def\pickupwholefraction#1.#2 {%
+ \global\advance\colcount by 1
+ \expandafter\xdef\csname col\the\colcount\endcsname{.#2\hsize}%
+ \setuptable
+}
+
+\newcount\colcount
+\def\setuptable#1{%
+ \def\firstarg{#1}%
+ \ifx\firstarg\xendsetuptable
+ \let\go = \relax
+ \else
+ \ifx\firstarg\xcolumnfractions
+ \global\setpercenttrue
+ \else
+ \ifsetpercent
+ \let\go\pickupwholefraction
+ \else
+ \global\advance\colcount by 1
+ \setbox0=\hbox{#1\unskip }% Add a normal word space as a separator;
+ % typically that is always in the input, anyway.
+ \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}%
+ \fi
+ \fi
+ \ifx\go\pickupwholefraction
+ % Put the argument back for the \pickupwholefraction call, so
+ % we'll always have a period there to be parsed.
+ \def\go{\pickupwholefraction#1}%
+ \else
+ \let\go = \setuptable
+ \fi%
+ \fi
+ \go
+}
+
+% This used to have \hskip1sp. But then the space in a template line is
+% not enough. That is bad. So let's go back to just & until we
+% encounter the problem it was intended to solve again.
+% --karl, nathan@acm.org, 20apr99.
+\def\tab{&}
+
+% @multitable ... @end multitable definitions:
+%
+\def\multitable{\parsearg\dotable}
+\def\dotable#1{\bgroup
+ \vskip\parskip
+ \let\item\crcr
+ \tolerance=9500
+ \hbadness=9500
+ \setmultitablespacing
+ \parskip=\multitableparskip
+ \parindent=\multitableparindent
+ \overfullrule=0pt
+ \global\colcount=0
+ \def\Emultitable{\global\setpercentfalse\cr\egroup\egroup}%
+ %
+ % To parse everything between @multitable and @item:
+ \setuptable#1 \endsetuptable
+ %
+ % \everycr will reset column counter, \colcount, at the end of
+ % each line. Every column entry will cause \colcount to advance by one.
+ % The table preamble
+ % looks at the current \colcount to find the correct column width.
+ \everycr{\noalign{%
+ %
+ % \filbreak%% keeps underfull box messages off when table breaks over pages.
+ % Maybe so, but it also creates really weird page breaks when the table
+ % breaks over pages. Wouldn't \vfil be better? Wait until the problem
+ % manifests itself, so it can be fixed for real --karl.
+ \global\colcount=0\relax}}%
+ %
+ % This preamble sets up a generic column definition, which will
+ % be used as many times as user calls for columns.
+ % \vtop will set a single line and will also let text wrap and
+ % continue for many paragraphs if desired.
+ \halign\bgroup&\global\advance\colcount by 1\relax
+ \multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname
+ %
+ % In order to keep entries from bumping into each other
+ % we will add a \leftskip of \multitablecolspace to all columns after
+ % the first one.
+ %
+ % If a template has been used, we will add \multitablecolspace
+ % to the width of each template entry.
+ %
+ % If the user has set preamble in terms of percent of \hsize we will
+ % use that dimension as the width of the column, and the \leftskip
+ % will keep entries from bumping into each other. Table will start at
+ % left margin and final column will justify at right margin.
+ %
+ % Make sure we don't inherit \rightskip from the outer environment.
+ \rightskip=0pt
+ \ifnum\colcount=1
+ % The first column will be indented with the surrounding text.
+ \advance\hsize by\leftskip
+ \else
+ \ifsetpercent \else
+ % If user has not set preamble in terms of percent of \hsize
+ % we will advance \hsize by \multitablecolspace.
+ \advance\hsize by \multitablecolspace
+ \fi
+ % In either case we will make \leftskip=\multitablecolspace:
+ \leftskip=\multitablecolspace
+ \fi
+ % Ignoring space at the beginning and end avoids an occasional spurious
+ % blank line, when TeX decides to break the line at the space before the
+ % box from the multistrut, so the strut ends up on a line by itself.
+ % For example:
+ % @multitable @columnfractions .11 .89
+ % @item @code{#}
+ % @tab Legal holiday which is valid in major parts of the whole country.
+ % Is automatically provided with highlighting sequences respectively marking
+ % characters.
+ \noindent\ignorespaces##\unskip\multistrut}\cr
+}
+
+\def\setmultitablespacing{% test to see if user has set \multitablelinespace.
+% If so, do nothing. If not, give it an appropriate dimension based on
+% current baselineskip.
+\ifdim\multitablelinespace=0pt
+%% strut to put in table in case some entry doesn't have descenders,
+%% to keep lines equally spaced
+\let\multistrut = \strut
+%% Test to see if parskip is larger than space between lines of
+%% table. If not, do nothing.
+%% If so, set to same dimension as multitablelinespace.
+\else
+\gdef\multistrut{\vrule height\multitablelinespace depth\dp0
+width0pt\relax} \fi
+\ifdim\multitableparskip>\multitablelinespace
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+\fi%
+\ifdim\multitableparskip=0pt
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+\fi}
+
+
+\message{conditionals,}
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+ \let\chapter=\relax
+ \let\unnumbered=\relax
+ \let\top=\relax
+ \let\unnumberedsec=\relax
+ \let\unnumberedsection=\relax
+ \let\unnumberedsubsec=\relax
+ \let\unnumberedsubsection=\relax
+ \let\unnumberedsubsubsec=\relax
+ \let\unnumberedsubsubsection=\relax
+ \let\section=\relax
+ \let\subsec=\relax
+ \let\subsubsec=\relax
+ \let\subsection=\relax
+ \let\subsubsection=\relax
+ \let\appendix=\relax
+ \let\appendixsec=\relax
+ \let\appendixsection=\relax
+ \let\appendixsubsec=\relax
+ \let\appendixsubsection=\relax
+ \let\appendixsubsubsec=\relax
+ \let\appendixsubsubsection=\relax
+ \let\contents=\relax
+ \let\smallbook=\relax
+ \let\titlepage=\relax
+}
+
+% Used in nested conditionals, where we have to parse the Texinfo source
+% and so want to turn off most commands, in case they are used
+% incorrectly.
+%
+\def\ignoremorecommands{%
+ \let\defcodeindex = \relax
+ \let\defcv = \relax
+ \let\deffn = \relax
+ \let\deffnx = \relax
+ \let\defindex = \relax
+ \let\defivar = \relax
+ \let\defmac = \relax
+ \let\defmethod = \relax
+ \let\defop = \relax
+ \let\defopt = \relax
+ \let\defspec = \relax
+ \let\deftp = \relax
+ \let\deftypefn = \relax
+ \let\deftypefun = \relax
+ \let\deftypeivar = \relax
+ \let\deftypevar = \relax
+ \let\deftypevr = \relax
+ \let\defun = \relax
+ \let\defvar = \relax
+ \let\defvr = \relax
+ \let\ref = \relax
+ \let\xref = \relax
+ \let\printindex = \relax
+ \let\pxref = \relax
+ \let\settitle = \relax
+ \let\setchapternewpage = \relax
+ \let\setchapterstyle = \relax
+ \let\everyheading = \relax
+ \let\evenheading = \relax
+ \let\oddheading = \relax
+ \let\everyfooting = \relax
+ \let\evenfooting = \relax
+ \let\oddfooting = \relax
+ \let\headings = \relax
+ \let\include = \relax
+ \let\lowersections = \relax
+ \let\down = \relax
+ \let\raisesections = \relax
+ \let\up = \relax
+ \let\set = \relax
+ \let\clear = \relax
+ \let\item = \relax
+}
+
+% Ignore @ignore ... @end ignore.
+%
+\def\ignore{\doignore{ignore}}
+
+% Ignore @ifinfo, @ifhtml, @ifnottex, @html, @menu, and @direntry text.
+%
+\def\ifinfo{\doignore{ifinfo}}
+\def\ifhtml{\doignore{ifhtml}}
+\def\ifnottex{\doignore{ifnottex}}
+\def\html{\doignore{html}}
+\def\menu{\doignore{menu}}
+\def\direntry{\doignore{direntry}}
+
+% @dircategory CATEGORY -- specify a category of the dir file
+% which this file should belong to. Ignore this in TeX.
+\let\dircategory = \comment
+
+% Ignore text until a line `@end #1'.
+%
+\def\doignore#1{\begingroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define a command to swallow text until we reach `@end #1'.
+ % This @ is a catcode 12 token (that is the normal catcode of @ in
+ % this texinfo.tex file). We change the catcode of @ below to match.
+ \long\def\doignoretext##1@end #1{\enddoignore}%
+ %
+ % Make sure that spaces turn into tokens that match what \doignoretext wants.
+ \catcode32 = 10
+ %
+ % Ignore braces, too, so mismatched braces don't cause trouble.
+ \catcode`\{ = 9
+ \catcode`\} = 9
+ %
+ % We must not have @c interpreted as a control sequence.
+ \catcode`\@ = 12
+ %
+ % Make the letter c a comment character so that the rest of the line
+ % will be ignored. This way, the document can have (for example)
+ % @c @end ifinfo
+ % and the @end ifinfo will be properly ignored.
+ % (We've just changed @ to catcode 12.)
+ \catcode`\c = 14
+ %
+ % And now expand that command.
+ \doignoretext
+}
+
+% What we do to finish off ignored text.
+%
+\def\enddoignore{\endgroup\ignorespaces}%
+
+\newif\ifwarnedobs\warnedobsfalse
+\def\obstexwarn{%
+ \ifwarnedobs\relax\else
+ % We need to warn folks that they may have trouble with TeX 3.0.
+ % This uses \immediate\write16 rather than \message to get newlines.
+ \immediate\write16{}
+ \immediate\write16{WARNING: for users of Unix TeX 3.0!}
+ \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
+ \immediate\write16{If you are running another version of TeX, relax.}
+ \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
+ \immediate\write16{ Then upgrade your TeX installation if you can.}
+ \immediate\write16{ (See ftp://ftp.gnu.org/pub/gnu/TeX.README.)}
+ \immediate\write16{If you are stuck with version 3.0, run the}
+ \immediate\write16{ script ``tex3patch'' from the Texinfo distribution}
+ \immediate\write16{ to use a workaround.}
+ \immediate\write16{}
+ \global\warnedobstrue
+ \fi
+}
+
+% **In TeX 3.0, setting text in \nullfont hangs tex. For a
+% workaround (which requires the file ``dummy.tfm'' to be installed),
+% uncomment the following line:
+%%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+
+% Ignore text, except that we keep track of conditional commands for
+% purposes of nesting, up to an `@end #1' command.
+%
+\def\nestedignore#1{%
+ \obstexwarn
+ % We must actually expand the ignored text to look for the @end
+ % command, so that nested ignore constructs work. Thus, we put the
+ % text into a \vbox and then do nothing with the result. To minimize
+ % the change of memory overflow, we follow the approach outlined on
+ % page 401 of the TeXbook: make the current font be a dummy font.
+ %
+ \setbox0 = \vbox\bgroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define `@end #1' to end the box, which will in turn undefine the
+ % @end command again.
+ \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
+ %
+ % We are going to be parsing Texinfo commands. Most cause no
+ % trouble when they are used incorrectly, but some commands do
+ % complicated argument parsing or otherwise get confused, so we
+ % undefine them.
+ %
+ % We can't do anything about stray @-signs, unfortunately;
+ % they'll produce `undefined control sequence' errors.
+ \ignoremorecommands
+ %
+ % Set the current font to be \nullfont, a TeX primitive, and define
+ % all the font commands to also use \nullfont. We don't use
+ % dummy.tfm, as suggested in the TeXbook, because not all sites
+ % might have that installed. Therefore, math mode will still
+ % produce output, but that should be an extremely small amount of
+ % stuff compared to the main input.
+ %
+ \nullfont
+ \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont
+ \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont
+ \let\tensf = \nullfont
+ % Similarly for index fonts (mostly for their use in
+ % smallexample)
+ \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont
+ \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont
+ \let\indsf = \nullfont
+ %
+ % Don't complain when characters are missing from the fonts.
+ \tracinglostchars = 0
+ %
+ % Don't bother to do space factor calculations.
+ \frenchspacing
+ %
+ % Don't report underfull hboxes.
+ \hbadness = 10000
+ %
+ % Do minimal line-breaking.
+ \pretolerance = 10000
+ %
+ % Do not execute instructions in @tex
+ \def\tex{\doignore{tex}}%
+ % Do not execute macro definitions.
+ % `c' is a comment character, so the word `macro' will get cut off.
+ \def\macro{\doignore{ma}}%
+}
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it. Make sure the catcode of space is correct to avoid
+% losing inside @example, for instance.
+%
+\def\set{\begingroup\catcode` =10
+ \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR.
+ \parsearg\setxxx}
+\def\setxxx#1{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+ \def\temp{#2}%
+ \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+ \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+ \fi
+ \endgroup
+}
+% Can't use \xdef to pre-expand #2 and save some time, since \temp or
+% \next or other control sequences that we've defined might get us into
+% an infinite loop. Consider `@set foo @cite{bar}'.
+\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+% @value{foo} gets the text saved in variable foo.
+{
+ \catcode`\_ = \active
+ %
+ % We might end up with active _ or - characters in the argument if
+ % we're called from @code, as @code{@value{foo-bar_}}. So \let any
+ % such active characters to their normal equivalents.
+ \gdef\value{\begingroup
+ \catcode`\-=12 \catcode`\_=12
+ \indexbreaks \let_\normalunderscore
+ \valuexxx}
+}
+\def\valuexxx#1{\expandablevalue{#1}\endgroup}
+
+% We have this subroutine so that we can handle at least some @value's
+% properly in indexes (we \let\value to this in \indexdummies). Ones
+% whose names contain - or _ still won't work, but we can't do anything
+% about that. The command has to be fully expandable, since the result
+% winds up in the index file. This means that if the variable's value
+% contains other Texinfo commands, it's almost certain it will fail
+% (although perhaps we could fix that with sufficient work to do a
+% one-level expansion on the result, instead of complete).
+%
+\def\expandablevalue#1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ {[No value for ``#1'']}%
+ \else
+ \csname SET#1\endcsname
+ \fi
+}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+\def\ifset{\parsearg\ifsetxxx}
+\def\ifsetxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifsetfail
+ \else
+ \expandafter\ifsetsucceed
+ \fi
+}
+\def\ifsetsucceed{\conditionalsucceed{ifset}}
+\def\ifsetfail{\nestedignore{ifset}}
+\defineunmatchedend{ifset}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+\def\ifclear{\parsearg\ifclearxxx}
+\def\ifclearxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifclearsucceed
+ \else
+ \expandafter\ifclearfail
+ \fi
+}
+\def\ifclearsucceed{\conditionalsucceed{ifclear}}
+\def\ifclearfail{\nestedignore{ifclear}}
+\defineunmatchedend{ifclear}
+
+% @iftex, @ifnothtml, @ifnotinfo always succeed; we read the text
+% following, through the first @end iftex (etc.). Make `@end iftex'
+% (etc.) valid only after an @iftex.
+%
+\def\iftex{\conditionalsucceed{iftex}}
+\def\ifnothtml{\conditionalsucceed{ifnothtml}}
+\def\ifnotinfo{\conditionalsucceed{ifnotinfo}}
+\defineunmatchedend{iftex}
+\defineunmatchedend{ifnothtml}
+\defineunmatchedend{ifnotinfo}
+
+% We can't just want to start a group at @iftex (for example) and end it
+% at @end iftex, since then @set commands inside the conditional have no
+% effect (they'd get reverted at the end of the group). So we must
+% define \Eiftex to redefine itself to be its previous value. (We can't
+% just define it to fail again with an ``unmatched end'' error, since
+% the @ifset might be nested.)
+%
+\def\conditionalsucceed#1{%
+ \edef\temp{%
+ % Remember the current value of \E#1.
+ \let\nece{prevE#1} = \nece{E#1}%
+ %
+ % At the `@end #1', redefine \E#1 to be its previous value.
+ \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+ }%
+ \temp
+}
+
+% We need to expand lots of \csname's, but we don't want to expand the
+% control sequences after we've constructed them.
+%
+\def\nece#1{\expandafter\noexpand\csname#1\endcsname}
+
+% @defininfoenclose.
+\let\definfoenclose=\comment
+
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index. The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+%
+\def\newindex#1{%
+ \iflinks
+ \expandafter\newwrite \csname#1indfile\endcsname
+ \openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+ \fi
+ \expandafter\xdef\csname#1index\endcsname{% % Define @#1index
+ \noexpand\doindex{#1}}
+}
+
+% @defindex foo == \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex#1{%
+ \iflinks
+ \expandafter\newwrite \csname#1indfile\endcsname
+ \openout \csname#1indfile\endcsname \jobname.#1
+ \fi
+ \expandafter\xdef\csname#1index\endcsname{%
+ \noexpand\docodeindex{#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+% The \closeout helps reduce unnecessary open files; the limit on the
+% Acorn RISC OS is a mere 16 files.
+\def\synindex#1 #2 {%
+ \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+ \expandafter\closeout\csname#1indfile\endcsname
+ \expandafter\let\csname#1indfile\endcsname=\synindexfoo
+ \expandafter\xdef\csname#1index\endcsname{% define \xxxindex
+ \noexpand\doindex{#2}}%
+}
+
+% @syncodeindex foo bar similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex#1 #2 {%
+ \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+ \expandafter\closeout\csname#1indfile\endcsname
+ \expandafter\let\csname#1indfile\endcsname=\synindexfoo
+ \expandafter\xdef\csname#1index\endcsname{% define \xxxindex
+ \noexpand\docodeindex{#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+% and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+\def\ { }%
+% Take care of the plain tex accent commands.
+\def\"{\realbackslash "}%
+\def\`{\realbackslash `}%
+\def\'{\realbackslash '}%
+\def\^{\realbackslash ^}%
+\def\~{\realbackslash ~}%
+\def\={\realbackslash =}%
+\def\b{\realbackslash b}%
+\def\c{\realbackslash c}%
+\def\d{\realbackslash d}%
+\def\u{\realbackslash u}%
+\def\v{\realbackslash v}%
+\def\H{\realbackslash H}%
+% Take care of the plain tex special European modified letters.
+\def\oe{\realbackslash oe}%
+\def\ae{\realbackslash ae}%
+\def\aa{\realbackslash aa}%
+\def\OE{\realbackslash OE}%
+\def\AE{\realbackslash AE}%
+\def\AA{\realbackslash AA}%
+\def\o{\realbackslash o}%
+\def\O{\realbackslash O}%
+\def\l{\realbackslash l}%
+\def\L{\realbackslash L}%
+\def\ss{\realbackslash ss}%
+% Take care of texinfo commands likely to appear in an index entry.
+% (Must be a way to avoid doing expansion at all, and thus not have to
+% laboriously list every single command here.)
+\def\@{@}% will be @@ when we switch to @ as escape char.
+% Need these in case \tex is in effect and \{ is a \delimiter again.
+% But can't use \lbracecmd and \rbracecmd because texindex assumes
+% braces and backslashes are used only as delimiters.
+\let\{ = \mylbrace
+\let\} = \myrbrace
+\def\_{{\realbackslash _}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+%\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\result{\realbackslash result}%
+\def\equiv{\realbackslash equiv}%
+\def\expansion{\realbackslash expansion}%
+\def\print{\realbackslash print}%
+\def\error{\realbackslash error}%
+\def\point{\realbackslash point}%
+\def\copyright{\realbackslash copyright}%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\uref##1{\realbackslash uref {##1}}%
+\def\url##1{\realbackslash url {##1}}%
+\def\env##1{\realbackslash env {##1}}%
+\def\command##1{\realbackslash command {##1}}%
+\def\option##1{\realbackslash option {##1}}%
+\def\dotless##1{\realbackslash dotless {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\,##1{\realbackslash ,{##1}}%
+\def\t##1{\realbackslash t {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\sc##1{\realbackslash sc {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+\def\dfn##1{\realbackslash dfn {##1}}%
+\def\emph##1{\realbackslash emph {##1}}%
+\def\acronym##1{\realbackslash acronym {##1}}%
+%
+% Handle some cases of @value -- where the variable name does not
+% contain - or _, and the value does not contain any
+% (non-fully-expandable) commands.
+\let\value = \expandablevalue
+%
+\unsepspaces
+% Turn off macro expansion
+\turnoffmacros
+}
+
+% If an index command is used in an @example environment, any spaces
+% therein should become regular spaces in the raw index file, not the
+% expansion of \tie (\\leavevmode \penalty \@M \ ).
+{\obeyspaces
+ \gdef\unsepspaces{\obeyspaces\let =\space}}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+% Just ignore accents.
+\let\,=\indexdummyfont
+\let\"=\indexdummyfont
+\let\`=\indexdummyfont
+\let\'=\indexdummyfont
+\let\^=\indexdummyfont
+\let\~=\indexdummyfont
+\let\==\indexdummyfont
+\let\b=\indexdummyfont
+\let\c=\indexdummyfont
+\let\d=\indexdummyfont
+\let\u=\indexdummyfont
+\let\v=\indexdummyfont
+\let\H=\indexdummyfont
+\let\dotless=\indexdummyfont
+% Take care of the plain tex special European modified letters.
+\def\oe{oe}%
+\def\ae{ae}%
+\def\aa{aa}%
+\def\OE{OE}%
+\def\AE{AE}%
+\def\AA{AA}%
+\def\o{o}%
+\def\O{O}%
+\def\l{l}%
+\def\L{L}%
+\def\ss{ss}%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the active chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\url=\indexdummyfont
+\let\uref=\indexdummyfont
+\let\env=\indexdummyfont
+\let\command=\indexdummyfont
+\let\option=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+\def\@{@}%
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+ @gdef@realbackslash{\}}
+
+\let\indexbackslash=0 %overridden during \printindex.
+\let\SETmarginindex=\relax % put index entries in margin (undocumented)?
+
+% For \ifx comparisons.
+\def\emptymacro{\empty}
+
+% Most index entries go through here, but \dosubind is the general case.
+%
+\def\doind#1#2{\dosubind{#1}{#2}\empty}
+
+% Workhorse for all \fooindexes.
+% #1 is name of index, #2 is stuff to put there, #3 is subentry --
+% \empty if called from \doind, as we usually are. The main exception
+% is with defuns, which call us directly.
+%
+\def\dosubind#1#2#3{%
+ % Put the index entry in the margin if desired.
+ \ifx\SETmarginindex\relax\else
+ \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}%
+ \fi
+ {%
+ \count255=\lastpenalty
+ {%
+ \indexdummies % Must do this here, since \bf, etc expand at this stage
+ \escapechar=`\\
+ {%
+ \let\folio = 0% We will expand all macros now EXCEPT \folio.
+ \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+ % so it will be output as is; and it will print as backslash.
+ %
+ \def\thirdarg{#3}%
+ %
+ % If third arg is present, precede it with space in sort key.
+ \ifx\thirdarg\emptymacro
+ \let\subentry = \empty
+ \else
+ \def\subentry{ #3}%
+ \fi
+ %
+ % First process the index entry with all font commands turned
+ % off to get the string to sort by.
+ {\indexnofonts \xdef\indexsorttmp{#2\subentry}}%
+ %
+ % Now the real index entry with the fonts.
+ \toks0 = {#2}%
+ %
+ % If third (subentry) arg is present, add it to the index
+ % string. And include a space.
+ \ifx\thirdarg\emptymacro \else
+ \toks0 = \expandafter{\the\toks0 \space #3}%
+ \fi
+ %
+ % Set up the complete index entry, with both the sort key
+ % and the original text, including any font commands. We write
+ % three arguments to \entry to the .?? file, texindex reduces to
+ % two when writing the .??s sorted result.
+ \edef\temp{%
+ \write\csname#1indfile\endcsname{%
+ \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}%
+ }%
+ %
+ % If a skip is the last thing on the list now, preserve it
+ % by backing up by \lastskip, doing the \write, then inserting
+ % the skip again. Otherwise, the whatsit generated by the
+ % \write will make \lastskip zero. The result is that sequences
+ % like this:
+ % @end defun
+ % @tindex whatever
+ % @defun ...
+ % will have extra space inserted, because the \medbreak in the
+ % start of the @defun won't see the skip inserted by the @end of
+ % the previous defun.
+ %
+ % But don't do any of this if we're not in vertical mode. We
+ % don't want to do a \vskip and prematurely end a paragraph.
+ %
+ % Avoid page breaks due to these extra skips, too.
+ %
+ \iflinks
+ \ifvmode
+ \skip0 = \lastskip
+ \ifdim\lastskip = 0pt \else \nobreak\vskip-\lastskip \fi
+ \fi
+ %
+ \temp % do the write
+ %
+ %
+ \ifvmode \ifdim\skip0 = 0pt \else \nobreak\vskip\skip0 \fi \fi
+ \fi
+ }%
+ }%
+ \penalty\count255
+ }%
+}
+
+% The index entry written in the file actually looks like
+% \entry {sortstring}{page}{topic}
+% or
+% \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+% \initial {c}
+% before the first topic whose initial is c
+% \entry {topic}{pagelist}
+% for a topic that is used without subtopics
+% \primary {topic}
+% for the beginning of a topic that is used with subtopics
+% \secondary {subtopic}{pagelist}
+% for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% @printindex causes a particular index (the ??s file) to get printed.
+% It does not print any chapter heading (usually an @unnumbered).
+%
+\def\printindex{\parsearg\doprintindex}
+\def\doprintindex#1{\begingroup
+ \dobreak \chapheadingskip{10000}%
+ %
+ \indexfonts \rm
+ \tolerance = 9500
+ \indexbreaks
+ %
+ % See if the index file exists and is nonempty.
+ % Change catcode of @ here so that if the index file contains
+ % \initial {@}
+ % as its first line, TeX doesn't complain about mismatched braces
+ % (because it thinks @} is a control sequence).
+ \catcode`\@ = 11
+ \openin 1 \jobname.#1s
+ \ifeof 1
+ % \enddoublecolumns gets confused if there is no text in the index,
+ % and it loses the chapter title and the aux file entries for the
+ % index. The easiest way to prevent this problem is to make sure
+ % there is some text.
+ \putwordIndexNonexistent
+ \else
+ %
+ % If the index file exists but is empty, then \openin leaves \ifeof
+ % false. We have to make TeX try to read something from the file, so
+ % it can discover if there is anything in it.
+ \read 1 to \temp
+ \ifeof 1
+ \putwordIndexIsEmpty
+ \else
+ % Index files are almost Texinfo source, but we use \ as the escape
+ % character. It would be better to use @, but that's too big a change
+ % to make right now.
+ \def\indexbackslash{\rawbackslashxx}%
+ \catcode`\\ = 0
+ \escapechar = `\\
+ \begindoublecolumns
+ \input \jobname.#1s
+ \enddoublecolumns
+ \fi
+ \fi
+ \closein 1
+\endgroup}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+\def\initial#1{{%
+ % Some minor font changes for the special characters.
+ \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+ %
+ % Remove any glue we may have, we'll be inserting our own.
+ \removelastskip
+ %
+ % We like breaks before the index initials, so insert a bonus.
+ \penalty -300
+ %
+ % Typeset the initial. Making this add up to a whole number of
+ % baselineskips increases the chance of the dots lining up from column
+ % to column. It still won't often be perfect, because of the stretch
+ % we need before each entry, but it's better.
+ %
+ % No shrink because it confuses \balancecolumns.
+ \vskip 1.67\baselineskip plus .5\baselineskip
+ \leftline{\secbf #1}%
+ \vskip .33\baselineskip plus .1\baselineskip
+ %
+ % Do our best not to break after the initial.
+ \nobreak
+}}
+
+% This typesets a paragraph consisting of #1, dot leaders, and then #2
+% flush to the right margin. It is used for index and table of contents
+% entries. The paragraph is indented by \leftskip.
+%
+\def\entry#1#2{\begingroup
+ %
+ % Start a new paragraph if necessary, so our assignments below can't
+ % affect previous text.
+ \par
+ %
+ % Do not fill out the last line with white space.
+ \parfillskip = 0in
+ %
+ % No extra space above this paragraph.
+ \parskip = 0in
+ %
+ % Do not prefer a separate line ending with a hyphen to fewer lines.
+ \finalhyphendemerits = 0
+ %
+ % \hangindent is only relevant when the entry text and page number
+ % don't both fit on one line. In that case, bob suggests starting the
+ % dots pretty far over on the line. Unfortunately, a large
+ % indentation looks wrong when the entry text itself is broken across
+ % lines. So we use a small indentation and put up with long leaders.
+ %
+ % \hangafter is reset to 1 (which is the value we want) at the start
+ % of each paragraph, so we need not do anything with that.
+ \hangindent = 2em
+ %
+ % When the entry text needs to be broken, just fill out the first line
+ % with blank space.
+ \rightskip = 0pt plus1fil
+ %
+ % A bit of stretch before each entry for the benefit of balancing columns.
+ \vskip 0pt plus1pt
+ %
+ % Start a ``paragraph'' for the index entry so the line breaking
+ % parameters we've set above will have an effect.
+ \noindent
+ %
+ % Insert the text of the index entry. TeX will do line-breaking on it.
+ #1%
+ % The following is kludged to not output a line of dots in the index if
+ % there are no page numbers. The next person who breaks this will be
+ % cursed by a Unix daemon.
+ \def\tempa{{\rm }}%
+ \def\tempb{#2}%
+ \edef\tempc{\tempa}%
+ \edef\tempd{\tempb}%
+ \ifx\tempc\tempd\ \else%
+ %
+ % If we must, put the page number on a line of its own, and fill out
+ % this line with blank space. (The \hfil is overwhelmed with the
+ % fill leaders glue in \indexdotfill if the page number does fit.)
+ \hfil\penalty50
+ \null\nobreak\indexdotfill % Have leaders before the page number.
+ %
+ % The `\ ' here is removed by the implicit \unskip that TeX does as
+ % part of (the primitive) \par. Without it, a spurious underfull
+ % \hbox ensues.
+ \ #2% The page number ends the paragraph.
+ \fi%
+ \par
+\endgroup}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+ \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
+}}
+
+% Define two-column mode, which we use to typeset indexes.
+% Adapted from the TeXbook, page 416, which is to say,
+% the manmac.tex format used to print the TeXbook itself.
+\catcode`\@=11
+
+\newbox\partialpage
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns
+ % Grab any single-column material above us.
+ \output = {%
+ %
+ % Here is a possibility not foreseen in manmac: if we accumulate a
+ % whole lot of material, we might end up calling this \output
+ % routine twice in a row (see the doublecol-lose test, which is
+ % essentially a couple of indexes with @setchapternewpage off). In
+ % that case we just ship out what is in \partialpage with the normal
+ % output routine. Generally, \partialpage will be empty when this
+ % runs and this will be a no-op. See the indexspread.tex test case.
+ \ifvoid\partialpage \else
+ \onepageout{\pagecontents\partialpage}%
+ \fi
+ %
+ \global\setbox\partialpage = \vbox{%
+ % Unvbox the main output page.
+ \unvbox\PAGE
+ \kern-\topskip \kern\baselineskip
+ }%
+ }%
+ \eject % run that output routine to set \partialpage
+ %
+ % Use the double-column output routine for subsequent pages.
+ \output = {\doublecolumnout}%
+ %
+ % Change the page size parameters. We could do this once outside this
+ % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+ % format, but then we repeat the same computation. Repeating a couple
+ % of assignments once per index is clearly meaningless for the
+ % execution time, so we may as well do it in one place.
+ %
+ % First we halve the line length, less a little for the gutter between
+ % the columns. We compute the gutter based on the line length, so it
+ % changes automatically with the paper format. The magic constant
+ % below is chosen so that the gutter has the same value (well, +-<1pt)
+ % as it did when we hard-coded it.
+ %
+ % We put the result in a separate register, \doublecolumhsize, so we
+ % can restore it in \pagesofar, after \hsize itself has (potentially)
+ % been clobbered.
+ %
+ \doublecolumnhsize = \hsize
+ \advance\doublecolumnhsize by -.04154\hsize
+ \divide\doublecolumnhsize by 2
+ \hsize = \doublecolumnhsize
+ %
+ % Double the \vsize as well. (We don't need a separate register here,
+ % since nobody clobbers \vsize.)
+ \advance\vsize by -\ht\partialpage
+ \vsize = 2\vsize
+}
+
+% The double-column output routine for all double-column pages except
+% the last.
+%
+\def\doublecolumnout{%
+ \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ % Get the available space for the double columns -- the normal
+ % (undoubled) page height minus any material left over from the
+ % previous page.
+ \dimen@ = \vsize
+ \divide\dimen@ by 2
+ %
+ % box0 will be the left-hand column, box2 the right.
+ \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+ \onepageout\pagesofar
+ \unvbox255
+ \penalty\outputpenalty
+}
+\def\pagesofar{%
+ % Re-output the contents of the output page -- any previous material,
+ % followed by the two boxes we just split, in box0 and box2.
+ \unvbox\partialpage
+ %
+ \hsize = \doublecolumnhsize
+ \wd0=\hsize \wd2=\hsize
+ \hbox to\pagewidth{\box0\hfil\box2}%
+}
+\def\enddoublecolumns{%
+ \output = {%
+ % Split the last of the double-column material. Leave it on the
+ % current page, no automatic page break.
+ \balancecolumns
+ %
+ % If we end up splitting too much material for the current page,
+ % though, there will be another page break right after this \output
+ % invocation ends. Having called \balancecolumns once, we do not
+ % want to call it again. Therefore, reset \output to its normal
+ % definition right away. (We hope \balancecolumns will never be
+ % called on to balance too much material, but if it is, this makes
+ % the output somewhat more palatable.)
+ \global\output = {\onepageout{\pagecontents\PAGE}}%
+ }%
+ \eject
+ \endgroup % started in \begindoublecolumns
+ %
+ % \pagegoal was set to the doubled \vsize above, since we restarted
+ % the current page. We're now back to normal single-column
+ % typesetting, so reset \pagegoal to the normal \vsize (after the
+ % \endgroup where \vsize got restored).
+ \pagegoal = \vsize
+}
+\def\balancecolumns{%
+ % Called at the end of the double column material.
+ \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120.
+ \dimen@ = \ht0
+ \advance\dimen@ by \topskip
+ \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by 2 % target to split to
+ %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}%
+ \splittopskip = \topskip
+ % Loop until we get a decent breakpoint.
+ {%
+ \vbadness = 10000
+ \loop
+ \global\setbox3 = \copy0
+ \global\setbox1 = \vsplit3 to \dimen@
+ \ifdim\ht3>\dimen@
+ \global\advance\dimen@ by 1pt
+ \repeat
+ }%
+ %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}%
+ \setbox0=\vbox to\dimen@{\unvbox1}%
+ \setbox2=\vbox to\dimen@{\unvbox3}%
+ %
+ \pagesofar
+}
+\catcode`\@ = \other
+
+
+\message{sectioning,}
+% Chapters, sections, etc.
+
+\newcount\chapno
+\newcount\secno \secno=0
+\newcount\subsecno \subsecno=0
+\newcount\subsubsecno \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+% The \the is necessary, despite appearances, because \appendixletter is
+% expanded while writing the .toc file. \char\appendixno is not
+% expandable, thus it is written literally, thus all appendixes come out
+% with the same letter (or @) in the toc without it.
+\newcount\appendixno \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it. @section does likewise.
+\def\thischapter{}
+\def\thissection{}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raise/lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% Choose a numbered-heading macro
+% #1 is heading level if unmodified by @raisesections or @lowersections
+% #2 is text for heading
+\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \chapterzzz{#2}
+\or
+ \seczzz{#2}
+\or
+ \numberedsubseczzz{#2}
+\or
+ \numberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \chapterzzz{#2}
+ \else
+ \numberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses appendix heading levels
+\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \appendixzzz{#2}
+\or
+ \appendixsectionzzz{#2}
+\or
+ \appendixsubseczzz{#2}
+\or
+ \appendixsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \appendixzzz{#2}
+ \else
+ \appendixsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses numberless heading levels
+\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \unnumberedzzz{#2}
+\or
+ \unnumberedseczzz{#2}
+\or
+ \unnumberedsubseczzz{#2}
+\or
+ \unnumberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \unnumberedzzz{#2}
+ \else
+ \unnumberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% @chapter, @appendix, @unnumbered.
+\def\thischaptername{No Chapter Title}
+\outer\def\chapter{\parsearg\chapteryyy}
+\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz #1{%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \chapno by 1 \message{\putwordChapter\space \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}%
+ {\the\chapno}}}%
+\temp
+\donoderef
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+}
+
+\outer\def\appendix{\parsearg\appendixyyy}
+\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz #1{%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \appendixno by 1
+\message{\putwordAppendix\space \appendixletter}%
+\chapmacro {#1}{\putwordAppendix{} \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}%
+ {\putwordAppendix{} \appendixletter}}}%
+\temp
+\appendixnoderef
+\global\let\section = \appendixsec
+\global\let\subsection = \appendixsubsec
+\global\let\subsubsection = \appendixsubsubsec
+}
+
+% @centerchap is like @unnumbered, but the heading is centered.
+\outer\def\centerchap{\parsearg\centerchapyyy}
+\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}}
+
+% @top is like @unnumbered.
+\outer\def\top{\parsearg\unnumberedyyy}
+
+\outer\def\unnumbered{\parsearg\unnumberedyyy}
+\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz #1{%
+\secno=0 \subsecno=0 \subsubsecno=0
+%
+% This used to be simply \message{#1}, but TeX fully expands the
+% argument to \message. Therefore, if #1 contained @-commands, TeX
+% expanded them. For example, in `@unnumbered The @cite{Book}', TeX
+% expanded @cite (which turns out to cause errors because \cite is meant
+% to be executed, not expanded).
+%
+% Anyway, we don't want the fully-expanded definition of @cite to appear
+% as a result of the \message, we just want `@cite' itself. We use
+% \the<toks register> to achieve this: TeX expands \the<toks> only once,
+% simply yielding the contents of <toks register>. (We also do this for
+% the toc entries.)
+\toks0 = {#1}\message{(\the\toks0)}%
+%
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbchapentry{\the\toks0}}}%
+\temp
+\unnumbnoderef
+\global\let\section = \unnumberedsec
+\global\let\subsection = \unnumberedsubsec
+\global\let\subsubsection = \unnumberedsubsubsec
+}
+
+% Sections.
+\outer\def\numberedsec{\parsearg\secyyy}
+\def\secyyy #1{\numhead1{#1}} % normally calls seczzz
+\def\seczzz #1{%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}%
+ {\the\chapno}{\the\secno}}}%
+\temp
+\donoderef
+\nobreak
+}
+
+\outer\def\appendixsection{\parsearg\appendixsecyyy}
+\outer\def\appendixsec{\parsearg\appendixsecyyy}
+\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz #1{%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}%
+ {\appendixletter}{\the\secno}}}%
+\temp
+\appendixnoderef
+\nobreak
+}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz #1{%
+\plainsecheading {#1}\gdef\thissection{#1}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsecentry{\the\toks0}}}%
+\temp
+\unnumbnoderef
+\nobreak
+}
+
+% Subsections.
+\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz #1{%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}%
+ {\the\chapno}{\the\secno}{\the\subsecno}}}%
+\temp
+\donoderef
+\nobreak
+}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz #1{%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}%
+ {\appendixletter}{\the\secno}{\the\subsecno}}}%
+\temp
+\appendixnoderef
+\nobreak
+}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz #1{%
+\plainsubsecheading {#1}\gdef\thissection{#1}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsecentry%
+ {\the\toks0}}}%
+\temp
+\unnumbnoderef
+\nobreak
+}
+
+% Subsubsections.
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz #1{%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}%
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}%
+\temp
+\donoderef
+\nobreak
+}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz #1{%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}%
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}%
+\temp
+\appendixnoderef
+\nobreak
+}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz #1{%
+\plainsubsubsecheading {#1}\gdef\thissection{#1}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsubsecentry%
+ {\the\toks0}}}%
+\temp
+\unnumbnoderef
+\nobreak
+}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they should now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and such:
+% 1) We use \vbox rather than the earlier \line to permit
+% overlong headings to fold.
+% 2) \hyphenpenalty is set to 10000 because hyphenation in a
+% heading is obnoxious; this forbids it.
+% 3) Likewise, headings look best if no \parindent is used, and
+% if justification is not attempted. Hence \raggedright.
+
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+% @heading, @subheading, @subsubheading.
+\def\heading{\parsearg\plainsecheading}
+\def\subheading{\parsearg\plainsubsecheading}
+\def\subsubheading{\parsearg\plainsubsubsecheading}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip\chapheadingskip
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{%
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{%
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{
+\global\let\contentsalignmacro = \chapoddpage
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain
+\global\let\centerchapmacro=\centerchfplain}
+
+% Plain chapter opening.
+% #1 is the text, #2 the chapter number or empty if unnumbered.
+\def\chfplain#1#2{%
+ \pchapsepmacro
+ {%
+ \chapfonts \rm
+ \def\chapnum{#2}%
+ \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}%
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent = \wd0 \centerparametersmaybe
+ \unhbox0 #1\par}%
+ }%
+ \nobreak\bigskip % no page break after a chapter title
+ \nobreak
+}
+
+% Plain opening for unnumbered.
+\def\unnchfplain#1{\chfplain{#1}{}}
+
+% @centerchap -- centered and unnumbered.
+\let\centerparametersmaybe = \relax
+\def\centerchfplain#1{{%
+ \def\centerparametersmaybe{%
+ \advance\rightskip by 3\rightskip
+ \leftskip = \rightskip
+ \parfillskip = 0pt
+ }%
+ \chfplain{#1}{}%
+}}
+
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\nobreak
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\centerchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt
+ \hfill {\rm #1}\hfill}}\bigskip \par\nobreak
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen
+\global\let\centerchapmacro=\centerchfopen}
+
+
+% Section titles.
+\newskip\secheadingskip
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}}
+\def\plainsecheading#1{\sectionheading{sec}{}{#1}}
+
+% Subsection titles.
+\newskip \subsecheadingskip
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}}
+\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}}
+
+% Subsubsection titles.
+\let\subsubsecheadingskip = \subsecheadingskip
+\let\subsubsecheadingbreak = \subsecheadingbreak
+\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}}
+\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}}
+
+
+% Print any size section title.
+%
+% #1 is the section type (sec/subsec/subsubsec), #2 is the section
+% number (maybe empty), #3 the text.
+\def\sectionheading#1#2#3{%
+ {%
+ \expandafter\advance\csname #1headingskip\endcsname by \parskip
+ \csname #1headingbreak\endcsname
+ }%
+ {%
+ % Switch to the right set of fonts.
+ \csname #1fonts\endcsname \rm
+ %
+ % Only insert the separating space if we have a section number.
+ \def\secnum{#2}%
+ \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}%
+ %
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent = \wd0 % zero if no section number
+ \unhbox0 #3}%
+ }%
+ \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak
+}
+
+
+\message{toc,}
+% Table of contents.
+\newwrite\tocfile
+
+% Write an entry to the toc file, opening it if necessary.
+% Called from @chapter, etc. We supply {\folio} at the end of the
+% argument, which will end up as the last argument to the \...entry macro.
+%
+% We open the .toc file here instead of at @setfilename or any other
+% given time so that @contents can be put in the document anywhere.
+%
+\newif\iftocfileopened
+\def\writetocentry#1{%
+ \iftocfileopened\else
+ \immediate\openout\tocfile = \jobname.toc
+ \global\tocfileopenedtrue
+ \fi
+ \iflinks \write\tocfile{#1{\folio}}\fi
+}
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\newcount\savepageno
+\newcount\lastnegativepageno \lastnegativepageno = -1
+
+% Finish up the main text and prepare to read what we've written
+% to \tocfile.
+%
+\def\startcontents#1{%
+ % If @setchapternewpage on, and @headings double, the contents should
+ % start on an odd page, unlike chapters. Thus, we maintain
+ % \contentsalignmacro in parallel with \pagealignmacro.
+ % From: Torbjorn Granlund <tege@matematik.su.se>
+ \contentsalignmacro
+ \immediate\closeout\tocfile
+ %
+ % Don't need to put `Contents' or `Short Contents' in the headline.
+ % It is abundantly clear what they are.
+ \unnumbchapmacro{#1}\def\thischapter{}%
+ \savepageno = \pageno
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ % We can't do this, because then an actual ^ in a section
+ % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97.
+ %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi
+ \raggedbottom % Worry more about breakpoints than the bottom.
+ \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+ %
+ % Roman numerals for page numbers.
+ \ifnum \pageno>0 \pageno = \lastnegativepageno \fi
+}
+
+
+% Normal (long) toc.
+\def\contents{%
+ \startcontents{\putwordTOC}%
+ \openin 1 \jobname.toc
+ \ifeof 1 \else
+ \closein 1
+ \input \jobname.toc
+ \fi
+ \vfill \eject
+ \contentsalignmacro % in case @setchapternewpage odd is in effect
+ \endgroup
+ \lastnegativepageno = \pageno
+ \pageno = \savepageno
+}
+
+% And just the chapters.
+\def\summarycontents{%
+ \startcontents{\putwordShortTOC}%
+ %
+ \let\chapentry = \shortchapentry
+ \let\unnumbchapentry = \shortunnumberedentry
+ % We want a true roman here for the page numbers.
+ \secfonts
+ \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+ \rm
+ \hyphenpenalty = 10000
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\secentry ##1##2##3##4{}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \openin 1 \jobname.toc
+ \ifeof 1 \else
+ \closein 1
+ \input \jobname.toc
+ \fi
+ \vfill \eject
+ \contentsalignmacro % in case @setchapternewpage odd is in effect
+ \endgroup
+ \lastnegativepageno = \pageno
+ \pageno = \savepageno
+}
+\let\shortcontents = \summarycontents
+
+\ifpdf
+ \pdfcatalog{/PageMode /UseOutlines}%
+\fi
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+% See comments in \dochapentry re vbox and related settings
+\def\shortchapentry#1#2#3{%
+ \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}%
+}
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
+% We could simplify the code here by writing out an \appendixentry
+% command in the toc file for appendices, instead of using \chapentry
+% for both, but it doesn't seem worth it.
+\setbox0 = \hbox{\shortcontrm \putwordAppendix }
+\newdimen\shortappendixwidth \shortappendixwidth = \wd0
+
+\def\shortchaplabel#1{%
+ % We typeset #1 in a box of constant width, regardless of the text of
+ % #1, so the chapter titles will come out aligned.
+ \setbox0 = \hbox{#1}%
+ \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
+ %
+ % This space should be plenty, since a single number is .5em, and the
+ % widest letter (M) is 1em, at least in the Computer Modern fonts.
+ % (This space doesn't include the extra space that gets added after
+ % the label; that gets put in by \shortchapentry above.)
+ \advance\dimen0 by 1.1em
+ \hbox to \dimen0{#1\hfil}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{%
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we want it to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+ \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip
+ \begingroup
+ \chapentryfonts
+ \tocentry{#1}{\dopageno{#2}}%
+ \endgroup
+ \nobreak\vskip .25\baselineskip plus.1\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+ \secentryfonts \leftskip=\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+ \subsecentryfonts \leftskip=2\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+ \subsubsecentryfonts \leftskip=3\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+% Final typesetting of a toc entry; we use the same \entry macro as for
+% the index entries, but we want to suppress hyphenation here. (We
+% can't do that in the \entry macro, since index entries might consist
+% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+\def\tocentry#1#2{\begingroup
+ \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks
+ % Do not use \turnoffactive in these arguments. Since the toc is
+ % typeset in cmr, so characters such as _ would come out wrong; we
+ % have to do the usual translation tricks.
+ \entry{#1}{#2}%
+\endgroup}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+% @foo ... @end foo.
+
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox \newbox\longdblarrowbox
+\newbox\pushcharbox \newbox\bullbox
+\newbox\equivbox \newbox\errorbox
+
+%{\tentt
+%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+% depth .1ex\hfil}
+%}
+
+% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+\def\point{$\star$}
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% Adapted from the TeXbook's \boxit.
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+
+\global\setbox\errorbox=\hbox to \dimen0{\hfil
+ \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+ \advance\hsize by -2\dimen2 % Rules.
+ \vbox{
+ \hrule height\dimen2
+ \hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
+ \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+ \kern3pt\vrule width\dimen2}% Space to right.
+ \hrule height\dimen2}
+ \hfil}
+
+% The @error{} command.
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+ \catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+ \catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+ \catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+ \catcode `\%=14
+ \catcode 43=12 % plus
+ \catcode`\"=12
+ \catcode`\==12
+ \catcode`\|=12
+ \catcode`\<=12
+ \catcode`\>=12
+ \escapechar=`\\
+ %
+ \let\b=\ptexb
+ \let\bullet=\ptexbullet
+ \let\c=\ptexc
+ \let\,=\ptexcomma
+ \let\.=\ptexdot
+ \let\dots=\ptexdots
+ \let\equiv=\ptexequiv
+ \let\!=\ptexexclam
+ \let\i=\ptexi
+ \let\{=\ptexlbrace
+ \let\+=\tabalign
+ \let\}=\ptexrbrace
+ \let\*=\ptexstar
+ \let\t=\ptext
+ %
+ \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}%
+ \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}%
+ \def\@{@}%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^^M gets inside @lisp, @example, and other
+% such environments. \null is better than a space, since it doesn't
+% have any width.
+\def\lisppar{\null\endgraf}
+
+% Make each space character in the input produce a normal interword
+% space in the output. Don't allow a line break at this space, as this
+% is used only in environments like @example, where each line of input
+% should produce a line of output anyway.
+%
+{\obeyspaces %
+\gdef\sepspaces{\obeyspaces\let =\tie}}
+
+% Define \obeyedspace to be our active space, whatever it is. This is
+% for use in \parsearg.
+{\sepspaces%
+\global\let\obeyedspace= }
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical. We use \parskip here
+% to help in doing that, since in @example-like environments \parskip
+% is reset to zero; thus the \afterenvbreak inserts no space -- but the
+% start of the next paragraph will insert \parskip
+%
+\def\aboveenvbreak{{\advance\envskipamount by \parskip
+\endgraf \ifdim\lastskip<\envskipamount
+\removelastskip \penalty-50 \vskip\envskipamount \fi}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+% @cartouche ... @end cartouche: draw rectangle w/rounded corners around
+% environment contents.
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+ \ctl\leaders\hrule height\circthick\hfil\ctr
+ \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+ \cbl\leaders\hrule height\circthick\hfil\cbr
+ \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\long\def\cartouche{%
+\begingroup
+ \lskip=\leftskip \rskip=\rightskip
+ \leftskip=0pt\rightskip=0pt %we want these *outside*.
+ \cartinner=\hsize \advance\cartinner by-\lskip
+ \advance\cartinner by-\rskip
+ \cartouter=\hsize
+ \advance\cartouter by 18.4pt % allow for 3pt kerns on either
+% side, and for 6pt waste from
+% each corner char, and rule thickness
+ \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+ % Flag to tell @lisp, etc., not to narrow margin.
+ \let\nonarrowing=\comment
+ \vbox\bgroup
+ \baselineskip=0pt\parskip=0pt\lineskip=0pt
+ \carttop
+ \hbox\bgroup
+ \hskip\lskip
+ \vrule\kern3pt
+ \vbox\bgroup
+ \hsize=\cartinner
+ \kern3pt
+ \begingroup
+ \baselineskip=\normbskip
+ \lineskip=\normlskip
+ \parskip=\normpskip
+ \vskip -\parskip
+\def\Ecartouche{%
+ \endgroup
+ \kern3pt
+ \egroup
+ \kern3pt\vrule
+ \hskip\rskip
+ \egroup
+ \cartbot
+ \egroup
+\endgroup
+}}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+ \aboveenvbreak
+ \inENV % This group ends at the end of the body
+ \hfuzz = 12pt % Don't be fussy
+ \sepspaces % Make spaces be word-separators rather than space tokens.
+ \singlespace
+ \let\par = \lisppar % don't ignore blank lines
+ \obeylines % each line of input is a line of output
+ \parskip = 0pt
+ \parindent = 0pt
+ \emergencystretch = 0pt % don't try to avoid overfull boxes
+ % @cartouche defines \nonarrowing to inhibit narrowing
+ % at next level down.
+ \ifx\nonarrowing\relax
+ \advance \leftskip by \lispnarrowing
+ \exdentamount=\lispnarrowing
+ \let\exdent=\nofillexdent
+ \let\nonarrowing=\relax
+ \fi
+}
+
+% Define the \E... control sequence only if we are inside the particular
+% environment, so the error checking in \end will work.
+%
+% To end an @example-like environment, we first end the paragraph (via
+% \afterenvbreak's vertical glue), and then the group. That way we keep
+% the zero \parskip that the environments set -- \parskip glue will be
+% inserted at the beginning of the next paragraph in the document, after
+% the environment.
+%
+\def\nonfillfinish{\afterenvbreak\endgroup}
+
+% @lisp: indented, narrowed, typewriter font.
+\def\lisp{\begingroup
+ \nonfillstart
+ \let\Elisp = \nonfillfinish
+ \tt
+ \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
+ \gobble % eat return
+}
+
+% @example: Same as @lisp.
+\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp}
+
+% @small... is usually equivalent to the non-small (@smallbook
+% redefines). We must call \example (or whatever) last in the
+% definition, since it reads the return following the @example (or
+% whatever) command.
+%
+% This actually allows (for example) @end display inside an
+% @smalldisplay. Too bad, but makeinfo will catch the error anyway.
+%
+\def\smalldisplay{\begingroup\def\Esmalldisplay{\nonfillfinish\endgroup}\display}
+\def\smallexample{\begingroup\def\Esmallexample{\nonfillfinish\endgroup}\lisp}
+\def\smallformat{\begingroup\def\Esmallformat{\nonfillfinish\endgroup}\format}
+\def\smalllisp{\begingroup\def\Esmalllisp{\nonfillfinish\endgroup}\lisp}
+
+% Real @smallexample and @smalllisp (when @smallbook): use smaller fonts.
+% Originally contributed by Pavel@xerox.
+\def\smalllispx{\begingroup
+ \def\Esmalllisp{\nonfillfinish\endgroup}%
+ \def\Esmallexample{\nonfillfinish\endgroup}%
+ \indexfonts
+ \lisp
+}
+
+% @display: same as @lisp except keep current font.
+%
+\def\display{\begingroup
+ \nonfillstart
+ \let\Edisplay = \nonfillfinish
+ \gobble
+}
+
+% @smalldisplay (when @smallbook): @display plus smaller fonts.
+%
+\def\smalldisplayx{\begingroup
+ \def\Esmalldisplay{\nonfillfinish\endgroup}%
+ \indexfonts \rm
+ \display
+}
+
+% @format: same as @display except don't narrow margins.
+%
+\def\format{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eformat = \nonfillfinish
+ \gobble
+}
+
+% @smallformat (when @smallbook): @format plus smaller fonts.
+%
+\def\smallformatx{\begingroup
+ \def\Esmallformat{\nonfillfinish\endgroup}%
+ \indexfonts \rm
+ \format
+}
+
+% @flushleft (same as @format).
+%
+\def\flushleft{\begingroup \def\Eflushleft{\nonfillfinish\endgroup}\format}
+
+% @flushright.
+%
+\def\flushright{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushright = \nonfillfinish
+ \advance\leftskip by 0pt plus 1fill
+ \gobble
+}
+
+% @quotation does normal linebreaking (hence we can't use \nonfillstart)
+% and narrows the margins.
+%
+\def\quotation{%
+ \begingroup\inENV %This group ends at the end of the @quotation body
+ {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+ \singlespace
+ \parindent=0pt
+ % We have retained a nonzero parskip for the environment, since we're
+ % doing normal filling. So to avoid extra space below the environment...
+ \def\Equotation{\parskip = 0pt \nonfillfinish}%
+ %
+ % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
+ \ifx\nonarrowing\relax
+ \advance\leftskip by \lispnarrowing
+ \advance\rightskip by \lispnarrowing
+ \exdentamount = \lispnarrowing
+ \let\nonarrowing = \relax
+ \fi
+}
+
+
+\message{defuns,}
+% @defun etc.
+
+% Allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+% Be sure that we always have a definition for `(', etc. For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+\global\let(=\lparen \global\let)=\rparen
+\global\let[=\lbrack \global\let]=\rbrack
+
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+% This is used to turn on special parens
+% but make & act ordinary (given that it's active).
+\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested
+ \global\advance\parencount by 1
+}
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+ % also in that case restore the outer-level definition of (.
+ \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+ \global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text. This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}\global\advance\parencount by 1 }
+\def\clnr{{\sf\char`\)}\global\advance\parencount by -1 }
+\let\ampnr = \&
+\def\lbrb{{\bf\char`\[}}
+\def\rbrb{{\bf\char`\]}}
+
+% Active &'s sneak into the index arguments, so make sure it's defined.
+{
+ \catcode`& = 13
+ \global\let& = \ampnr
+}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+% Get the values of \leftskip and \rightskip as they were
+% outside the @def...
+\dimen2=\leftskip
+\advance\dimen2 by -\defbodyindent
+\noindent
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+{% Adjust \hsize to exclude the ambient margins,
+% so that \rightline will obey them.
+\advance \hsize by -\dimen2
+\rlap{\rightline{{\rm #2}\hskip -1.25pc }}}%
+% Make all lines underfull and no complaints:
+\tolerance=10000 \hbadness=10000
+\advance\leftskip by -\defbodyindent
+\exdentamount=\defbodyindent
+{\df #1}\enskip % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+% such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active % 61 is `='
+\obeylines\activeparens\spacesplit#3}
+
+% #1 is the \E... control sequence to end the definition (which we define).
+% #2 is the \...x control sequence for consecutive fns (which we define).
+% #3 is the control sequence to call to resume processing.
+% #4, delimited by the space, is the class name.
+%
+\def\defmethparsebody#1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+% @deftypemethod has an extra argument that nothing else does. Sigh.
+% #1 is the \E... control sequence to end the definition (which we define).
+% #2 is the \...x control sequence for consecutive fns (which we define).
+% #3 is the control sequence to call to resume processing.
+% #4, delimited by the space, is the class name.
+% #5 is the method's return type.
+%
+\def\deftypemethparsebody#1#2#3#4 #5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}{#5}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+
+\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\spacesplit#3}
+
+% This is used for \def{tp,vr}parsebody. It could probably be used for
+% some of the others, too, with some judicious conditionals.
+%
+\def\parsebodycommon#1#2#3{%
+ \begingroup\inENV %
+ \medbreak %
+ % Define the end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup\obeylines
+}
+
+\def\defvrparsebody#1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{#3{#4}}%
+}
+
+% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the
+% type is just `struct', because we lose the braces in `{struct
+% termios}' when \spacesplit reads its undelimited argument. Sigh.
+% \let\deftpparsebody=\defvrparsebody
+%
+% So, to get around this, we put \empty in with the type name. That
+% way, TeX won't find exactly `{...}' as an undelimited argument, and
+% won't strip off the braces.
+%
+\def\deftpparsebody #1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{\parsetpheaderline{#3{#4}}}\empty
+}
+
+% Fine, but then we have to eventually remove the \empty *and* the
+% braces (if any). That's what this does.
+%
+\def\removeemptybraces\empty#1\relax{#1}
+
+% After \spacesplit has done its work, this is called -- #1 is the final
+% thing to call, #2 the type name (which starts with \empty), and #3
+% (which might be empty) the arguments.
+%
+\def\parsetpheaderline#1#2#3{%
+ #1{\removeemptybraces#2\relax}{#3}%
+}%
+
+\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+% the first is all of #2 before the space token,
+% the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs#1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+% Set the font temporarily and use \font in case \setfont made \tensl a macro.
+{\tensl\hyphenchar\font=0}%
+#1%
+{\tensl\hyphenchar\font=45}%
+\ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\nobreak\vskip -\parskip\nobreak
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+% Use \boldbraxnoamp, not \functionparens, so that & is not special.
+\boldbraxnoamp
+\tclose{#1}% avoid \code because of side effects on active chars
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\nobreak\vskip -\parskip\nobreak
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{\putwordDeffunc}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type. #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\defheaderxcond#1\relax$$$#2}{\putwordDeftypefun}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% \defheaderxcond#1\relax$$$
+% puts #1 in @code, followed by a space, but does nothing if #1 is null.
+\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi}
+
+% #1 is the classification. #2 is the data type. #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup
+\normalparens % notably, turn off `&' magic, which prevents
+% at least some C++ text from working
+\defname {\defheaderxcond#2\relax$$$#3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{\putwordDefmac}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{\putwordDefspec}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defop CATEGORY CLASS OPERATION ARG...
+%
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+%
+\def\defopheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{\putwordon\ #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype\ \putwordon\ #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @deftypemethod CLASS RETURN-TYPE METHOD ARG...
+%
+\def\deftypemethod{%
+ \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader}
+%
+% #1 is the class name, #2 the data type, #3 the method name, #4 the args.
+\def\deftypemethodheader#1#2#3#4{%
+ \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index
+ \begingroup
+ \defname{\defheaderxcond#2\relax$$$#3}{\putwordMethodon\ \code{#1}}%
+ \deftypefunargs{#4}%
+ \endgroup
+}
+
+% @deftypeivar CLASS TYPE VARNAME
+%
+\def\deftypeivar{%
+ \deftypemethparsebody\Edeftypeivar\deftypeivarx\deftypeivarheader}
+%
+% #1 is the class name, #2 the data type, #3 the variable name.
+\def\deftypeivarheader#1#2#3{%
+ \dosubind{vr}{\code{#3}}{\putwordof\ \code{#1}}% entry in variable index
+ \begingroup
+ \defname{#3}{\putwordInstanceVariableof\ \code{#1}}%
+ \defvarargs{#3}%
+ \endgroup
+}
+
+% @defmethod == @defop Method
+%
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+%
+% #1 is the class name, #2 the method name, #3 the args.
+\def\defmethodheader#1#2#3{%
+ \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% entry in function index
+ \begingroup
+ \defname{#2}{\putwordMethodon\ \code{#1}}%
+ \defunargs{#3}%
+ \endgroup
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{\putwordof\ #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype\ \putwordof\ #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar CLASS VARNAME == @defcv {Instance Variable} CLASS VARNAME
+%
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+%
+\def\defivarheader#1#2#3{%
+ \dosubind {vr}{\code{#2}}{\putwordof\ #1}% entry in var index
+ \begingroup
+ \defname{#2}{\putwordInstanceVariableof\ #1}%
+ \defvarargs{#3}%
+ \endgroup
+}
+
+% @defvar
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\nobreak\vskip -\parskip\nobreak}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{\putwordDefvar}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{\putwordDefopt}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type. #2 is the name, perhaps followed by text that
+% is actually part of the data type, which should not be put into the index.
+\def\deftypevarheader #1#2{%
+\dovarind#2 \relax% Make entry in variables index
+\begingroup\defname {\defheaderxcond#1\relax$$$#2}{\putwordDeftypevar}%
+\interlinepenalty=10000
+\endgraf\nobreak\vskip -\parskip\nobreak
+\endgroup}
+\def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\dovarind#3 \relax%
+\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1}
+\interlinepenalty=10000
+\endgraf\nobreak\vskip -\parskip\nobreak
+\endgroup}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% These definitions are used if you use @defunx (etc.)
+% anywhere other than immediately after a @defun or @defunx.
+%
+\def\defcvx#1 {\errmessage{@defcvx in invalid context}}
+\def\deffnx#1 {\errmessage{@deffnx in invalid context}}
+\def\defivarx#1 {\errmessage{@defivarx in invalid context}}
+\def\defmacx#1 {\errmessage{@defmacx in invalid context}}
+\def\defmethodx#1 {\errmessage{@defmethodx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\defopx#1 {\errmessage{@defopx in invalid context}}
+\def\defspecx#1 {\errmessage{@defspecx in invalid context}}
+\def\deftpx#1 {\errmessage{@deftpx in invalid context}}
+\def\deftypefnx#1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypefunx#1 {\errmessage{@deftypefunx in invalid context}}
+\def\deftypeivarx#1 {\errmessage{@deftypeivarx in invalid context}}
+\def\deftypemethodx#1 {\errmessage{@deftypemethodx in invalid context}}
+\def\deftypevarx#1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx#1 {\errmessage{@deftypevrx in invalid context}}
+\def\defunx#1 {\errmessage{@defunx in invalid context}}
+\def\defvarx#1 {\errmessage{@defvarx in invalid context}}
+\def\defvrx#1 {\errmessage{@defvrx in invalid context}}
+
+
+\message{macros,}
+% @macro.
+
+% To do this right we need a feature of e-TeX, \scantokens,
+% which we arrange to emulate with a temporary file in ordinary TeX.
+\ifx\eTeXversion\undefined
+ \newwrite\macscribble
+ \def\scanmacro#1{%
+ \begingroup \newlinechar`\^^M
+ % Undo catcode changes of \startcontents and \doprintindex
+ \catcode`\@=0 \catcode`\\=12 \escapechar=`\@
+ % Append \endinput to make sure that TeX does not see the ending newline.
+ \toks0={#1\endinput}%
+ \immediate\openout\macscribble=\jobname.tmp
+ \immediate\write\macscribble{\the\toks0}%
+ \immediate\closeout\macscribble
+ \let\xeatspaces\eatspaces
+ \input \jobname.tmp
+ \endgroup
+}
+\else
+\def\scanmacro#1{%
+\begingroup \newlinechar`\^^M
+% Undo catcode changes of \startcontents and \doprintindex
+\catcode`\@=0 \catcode`\\=12 \escapechar=`\@
+\let\xeatspaces\eatspaces\scantokens{#1\endinput}\endgroup}
+\fi
+
+\newcount\paramno % Count of parameters
+\newtoks\macname % Macro name
+\newif\ifrecursive % Is it recursive?
+\def\macrolist{} % List of all defined macros in the form
+ % \do\macro1\do\macro2...
+
+% Utility routines.
+% Thisdoes \let #1 = #2, except with \csnames.
+\def\cslet#1#2{%
+\expandafter\expandafter
+\expandafter\let
+\expandafter\expandafter
+\csname#1\endcsname
+\csname#2\endcsname}
+
+% Trim leading and trailing spaces off a string.
+% Concepts from aro-bend problem 15 (see CTAN).
+{\catcode`\@=11
+\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }}
+\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@}
+\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @}
+\def\unbrace#1{#1}
+\unbrace{\gdef\trim@@@ #1 } #2@{#1}
+}
+
+% Trim a single trailing ^^M off a string.
+{\catcode`\^^M=12\catcode`\Q=3%
+\gdef\eatcr #1{\eatcra #1Q^^MQ}%
+\gdef\eatcra#1^^MQ{\eatcrb#1Q}%
+\gdef\eatcrb#1Q#2Q{#1}%
+}
+
+% Macro bodies are absorbed as an argument in a context where
+% all characters are catcode 10, 11 or 12, except \ which is active
+% (as in normal texinfo). It is necessary to change the definition of \.
+
+% It's necessary to have hard CRs when the macro is executed. This is
+% done by making ^^M (\endlinechar) catcode 12 when reading the macro
+% body, and then making it the \newlinechar in \scanmacro.
+
+\def\macrobodyctxt{%
+ \catcode`\~=12
+ \catcode`\^=12
+ \catcode`\_=12
+ \catcode`\|=12
+ \catcode`\<=12
+ \catcode`\>=12
+ \catcode`\+=12
+ \catcode`\{=12
+ \catcode`\}=12
+ \catcode`\@=12
+ \catcode`\^^M=12
+ \usembodybackslash}
+
+\def\macroargctxt{%
+ \catcode`\~=12
+ \catcode`\^=12
+ \catcode`\_=12
+ \catcode`\|=12
+ \catcode`\<=12
+ \catcode`\>=12
+ \catcode`\+=12
+ \catcode`\@=12
+ \catcode`\\=12}
+
+% \mbodybackslash is the definition of \ in @macro bodies.
+% It maps \foo\ => \csname macarg.foo\endcsname => #N
+% where N is the macro parameter number.
+% We define \csname macarg.\endcsname to be \realbackslash, so
+% \\ in macro replacement text gets you a backslash.
+
+{\catcode`@=0 @catcode`@\=@active
+ @gdef@usembodybackslash{@let\=@mbodybackslash}
+ @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname}
+}
+\expandafter\def\csname macarg.\endcsname{\realbackslash}
+
+\def\macro{\recursivefalse\parsearg\macroxxx}
+\def\rmacro{\recursivetrue\parsearg\macroxxx}
+
+\def\macroxxx#1{%
+ \getargs{#1}% now \macname is the macname and \argl the arglist
+ \ifx\argl\empty % no arguments
+ \paramno=0%
+ \else
+ \expandafter\parsemargdef \argl;%
+ \fi
+ \if1\csname ismacro.\the\macname\endcsname
+ \message{Warning: redefining \the\macname}%
+ \else
+ \expandafter\ifx\csname \the\macname\endcsname \relax
+ \else \errmessage{The name \the\macname\space is reserved}\fi
+ \global\cslet{macsave.\the\macname}{\the\macname}%
+ \global\expandafter\let\csname ismacro.\the\macname\endcsname=1%
+ % Add the macroname to \macrolist
+ \toks0 = \expandafter{\macrolist\do}%
+ \xdef\macrolist{\the\toks0
+ \expandafter\noexpand\csname\the\macname\endcsname}%
+ \fi
+ \begingroup \macrobodyctxt
+ \ifrecursive \expandafter\parsermacbody
+ \else \expandafter\parsemacbody
+ \fi}
+
+\def\unmacro{\parsearg\unmacroxxx}
+\def\unmacroxxx#1{%
+ \if1\csname ismacro.#1\endcsname
+ \global\cslet{#1}{macsave.#1}%
+ \global\expandafter\let \csname ismacro.#1\endcsname=0%
+ % Remove the macro name from \macrolist
+ \begingroup
+ \edef\tempa{\expandafter\noexpand\csname#1\endcsname}%
+ \def\do##1{%
+ \def\tempb{##1}%
+ \ifx\tempa\tempb
+ % remove this
+ \else
+ \toks0 = \expandafter{\newmacrolist\do}%
+ \edef\newmacrolist{\the\toks0\expandafter\noexpand\tempa}%
+ \fi}%
+ \def\newmacrolist{}%
+ % Execute macro list to define \newmacrolist
+ \macrolist
+ \global\let\macrolist\newmacrolist
+ \endgroup
+ \else
+ \errmessage{Macro #1 not defined}%
+ \fi
+}
+
+% This makes use of the obscure feature that if the last token of a
+% <parameter list> is #, then the preceding argument is delimited by
+% an opening brace, and that opening brace is not consumed.
+\def\getargs#1{\getargsxxx#1{}}
+\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs}
+\def\getmacname #1 #2\relax{\macname={#1}}
+\def\getmacargs#1{\def\argl{#1}}
+
+% Parse the optional {params} list. Set up \paramno and \paramlist
+% so \defmacro knows what to do. Define \macarg.blah for each blah
+% in the params list, to be ##N where N is the position in that list.
+% That gets used by \mbodybackslash (above).
+
+% We need to get `macro parameter char #' into several definitions.
+% The technique used is stolen from LaTeX: let \hash be something
+% unexpandable, insert that wherever you need a #, and then redefine
+% it to # just before using the token list produced.
+%
+% The same technique is used to protect \eatspaces till just before
+% the macro is used.
+
+\def\parsemargdef#1;{\paramno=0\def\paramlist{}%
+ \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,}
+\def\parsemargdefxxx#1,{%
+ \if#1;\let\next=\relax
+ \else \let\next=\parsemargdefxxx
+ \advance\paramno by 1%
+ \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname
+ {\xeatspaces{\hash\the\paramno}}%
+ \edef\paramlist{\paramlist\hash\the\paramno,}%
+ \fi\next}
+
+% These two commands read recursive and nonrecursive macro bodies.
+% (They're different since rec and nonrec macros end differently.)
+
+\long\def\parsemacbody#1@end macro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+\long\def\parsermacbody#1@end rmacro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+
+% This defines the macro itself. There are six cases: recursive and
+% nonrecursive macros of zero, one, and many arguments.
+% Much magic with \expandafter here.
+% \xdef is used so that macro definitions will survive the file
+% they're defined in; @include reads the file inside a group.
+\def\defmacro{%
+ \let\hash=##% convert placeholders to macro parameter chars
+ \ifrecursive
+ \ifcase\paramno
+ % 0
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \noexpand\scanmacro{\temp}}%
+ \or % 1
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \bgroup\noexpand\macroargctxt
+ \noexpand\braceorline
+ \expandafter\noexpand\csname\the\macname xxx\endcsname}%
+ \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+ \egroup\noexpand\scanmacro{\temp}}%
+ \else % many
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \bgroup\noexpand\macroargctxt
+ \noexpand\csname\the\macname xx\endcsname}%
+ \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+ \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+ \expandafter\expandafter
+ \expandafter\xdef
+ \expandafter\expandafter
+ \csname\the\macname xxx\endcsname
+ \paramlist{\egroup\noexpand\scanmacro{\temp}}%
+ \fi
+ \else
+ \ifcase\paramno
+ % 0
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \noexpand\norecurse{\the\macname}%
+ \noexpand\scanmacro{\temp}\egroup}%
+ \or % 1
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \bgroup\noexpand\macroargctxt
+ \noexpand\braceorline
+ \expandafter\noexpand\csname\the\macname xxx\endcsname}%
+ \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+ \egroup
+ \noexpand\norecurse{\the\macname}%
+ \noexpand\scanmacro{\temp}\egroup}%
+ \else % many
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \bgroup\noexpand\macroargctxt
+ \expandafter\noexpand\csname\the\macname xx\endcsname}%
+ \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+ \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+ \expandafter\expandafter
+ \expandafter\xdef
+ \expandafter\expandafter
+ \csname\the\macname xxx\endcsname
+ \paramlist{%
+ \egroup
+ \noexpand\norecurse{\the\macname}%
+ \noexpand\scanmacro{\temp}\egroup}%
+ \fi
+ \fi}
+
+\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}}
+
+% \braceorline decides whether the next nonwhitespace character is a
+% {. If so it reads up to the closing }, if not, it reads the whole
+% line. Whatever was read is then fed to the next control sequence
+% as an argument (by \parsebrace or \parsearg)
+\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx}
+\def\braceorlinexxx{%
+ \ifx\nchar\bgroup\else
+ \expandafter\parsearg
+ \fi \next}
+
+% We mant to disable all macros during \shipout so that they are not
+% expanded by \write.
+\def\turnoffmacros{\begingroup \def\do##1{\let\noexpand##1=\relax}%
+ \edef\next{\macrolist}\expandafter\endgroup\next}
+
+
+% @alias.
+\def\alias#1=#2{\gdef#1{#2}}
+
+
+\message{cross references,}
+% @xref etc.
+
+\newwrite\auxfile
+
+\newif\ifhavexrefs % True if xref values are known.
+\newif\ifwarnedxrefs % True if we warned once that they aren't known.
+
+% @inforef is relatively simple.
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
+ node \samp{\ignorespaces#1{}}}
+
+% @node's job is to define \lastnode.
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\nwnode=\node
+\let\lastnode=\relax
+
+% The sectioning commands (@chapter, etc.) call these.
+\def\donoderef{%
+ \ifx\lastnode\relax\else
+ \expandafter\expandafter\expandafter\setref{\lastnode}%
+ {Ysectionnumberandtype}%
+ \global\let\lastnode=\relax
+ \fi
+}
+\def\unnumbnoderef{%
+ \ifx\lastnode\relax\else
+ \expandafter\expandafter\expandafter\setref{\lastnode}{Ynothing}%
+ \global\let\lastnode=\relax
+ \fi
+}
+\def\appendixnoderef{%
+ \ifx\lastnode\relax\else
+ \expandafter\expandafter\expandafter\setref{\lastnode}%
+ {Yappendixletterandtype}%
+ \global\let\lastnode=\relax
+ \fi
+}
+
+
+% @anchor{NAME} -- define xref target at arbitrary point.
+%
+{ \catcode`\@ = 11
+% From latex.ltx, to make @anchor truely invisible.
+\newdimen\@savsk
+\newcount\@savsf
+\gdef\@bsphack{\relax
+ \ifhmode \@savsk\lastskip \@savsf\spacefactor \fi
+}
+\gdef\@esphack{\relax
+ \ifhmode \spacefactor\@savsf
+ \ifdim\@savsk>\z@ \ignorespaces \fi
+ \fi
+}
+\gdef\anchor#1{\@bsphack \setref{#1}{Ynothing}\@esphack}
+}
+
+% \setref{NAME}{SNT} defines a cross-reference point NAME, namely
+% NAME-title, NAME-pg, and NAME-SNT. Called from \foonoderef. We have
+% to set \indexdummies so commands such as @code in a section title
+% aren't expanded. It would be nicer not to expand the titles in the
+% first place, but there's so many layers that that is hard to do.
+%
+\def\setref#1#2{{%
+ \indexdummies
+ \ifpdf \pdfmkdest{#1}\fi
+ \dosetq{#1-title}{Ytitle}%
+ \dosetq{#1-pg}{Ypagenumber}%
+ \dosetq{#1-snt}{#2}%
+}}
+
+% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is
+% the node name, #2 the name of the Info cross-reference, #3 the printed
+% node name, #4 the name of the Info file, #5 the name of the printed
+% manual. All but the node name can be omitted.
+%
+\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]}
+\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
+ \def\printedmanual{\ignorespaces #5}%
+ \def\printednodename{\ignorespaces #3}%
+ \setbox1=\hbox{\printedmanual}%
+ \setbox0=\hbox{\printednodename}%
+ \ifdim \wd0 = 0pt
+ % No printed node name was explicitly given.
+ \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax
+ % Use the node name inside the square brackets.
+ \def\printednodename{\ignorespaces #1}%
+ \else
+ % Use the actual chapter/section title appear inside
+ % the square brackets. Use the real section title if we have it.
+ \ifdim \wd1 > 0pt
+ % It is in another manual, so we don't have it.
+ \def\printednodename{\ignorespaces #1}%
+ \else
+ \ifhavexrefs
+ % We know the real title if we have the xref values.
+ \def\printednodename{\refx{#1-title}{}}%
+ \else
+ % Otherwise just copy the Info node name.
+ \def\printednodename{\ignorespaces #1}%
+ \fi%
+ \fi
+ \fi
+ \fi
+ %
+ % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not
+ % insert empty discretionaries after hyphens, which means that it will
+ % not find a line break at a hyphen in a node names. Since some manuals
+ % are best written with fairly long node names, containing hyphens, this
+ % is a loss. Therefore, we give the text of the node name again, so it
+ % is as if TeX is seeing it for the first time.
+ \ifpdf
+ \leavevmode
+ \getfilename{#4}%
+ \ifnum\filenamelength>0
+ \pdfannotlink attr{/Border [0 0 0]}%
+ goto file{\the\filename.pdf} name{#1@}%
+ \else
+ \pdfannotlink attr{/Border [0 0 0]}%
+ goto name{#1@}%
+ \fi
+ \BlueGreen
+ \fi
+ %
+ \ifdim \wd1 > 0pt
+ \putwordsection{} ``\printednodename'' \putwordin{} \cite{\printedmanual}%
+ \else
+ % _ (for example) has to be the character _ for the purposes of the
+ % control sequence corresponding to the node, but it has to expand
+ % into the usual \leavevmode...\vrule stuff for purposes of
+ % printing. So we \turnoffactive for the \refx-snt, back on for the
+ % printing, back off for the \refx-pg.
+ {\normalturnoffactive
+ % Only output a following space if the -snt ref is nonempty; for
+ % @unnumbered and @anchor, it won't be.
+ \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}%
+ \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi
+ }%
+ % [mynode],
+ [\printednodename],\space
+ % page 3
+ \turnoffactive \putwordpage\tie\refx{#1-pg}{}%
+ \fi
+ \ifpdf \Black\pdfendlink \fi
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \normalturnoffactive so that punctuation chars such as underscore
+% and backslash work in node names. (\turnoffactive doesn't do \.)
+\def\dosetq#1#2{%
+ {\let\folio=0%
+ \normalturnoffactive
+ \edef\next{\write\auxfile{\internalsetq{#1}{#2}}}%
+ \iflinks
+ \next
+ \fi
+ }%
+}
+
+% \internalsetq {foo}{page} expands into
+% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thissection}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 \putwordChapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+ \let\linenumber = \empty % Non-3.0.
+\else
+ \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+
+\def\refx#1#2{%
+ \expandafter\ifx\csname X#1\endcsname\relax
+ % If not defined, say something at least.
+ \angleleft un\-de\-fined\angleright
+ \iflinks
+ \ifhavexrefs
+ \message{\linenumber Undefined cross reference `#1'.}%
+ \else
+ \ifwarnedxrefs\else
+ \global\warnedxrefstrue
+ \message{Cross reference values unknown; you must run TeX again.}%
+ \fi
+ \fi
+ \fi
+ \else
+ % It's defined, so just use it.
+ \csname X#1\endcsname
+ \fi
+ #2% Output the suffix in any case.
+}
+
+% This is the macro invoked by entries in the aux file.
+%
+\def\xrdef#1{\begingroup
+ % Reenable \ as an escape while reading the second argument.
+ \catcode`\\ = 0
+ \afterassignment\endgroup
+ \expandafter\gdef\csname X#1\endcsname
+}
+
+% Read the last existing aux file, if any. No error if none exists.
+\def\readauxfile{\begingroup
+ \catcode`\^^@=\other
+ \catcode`\^^A=\other
+ \catcode`\^^B=\other
+ \catcode`\^^C=\other
+ \catcode`\^^D=\other
+ \catcode`\^^E=\other
+ \catcode`\^^F=\other
+ \catcode`\^^G=\other
+ \catcode`\^^H=\other
+ \catcode`\^^K=\other
+ \catcode`\^^L=\other
+ \catcode`\^^N=\other
+ \catcode`\^^P=\other
+ \catcode`\^^Q=\other
+ \catcode`\^^R=\other
+ \catcode`\^^S=\other
+ \catcode`\^^T=\other
+ \catcode`\^^U=\other
+ \catcode`\^^V=\other
+ \catcode`\^^W=\other
+ \catcode`\^^X=\other
+ \catcode`\^^Z=\other
+ \catcode`\^^[=\other
+ \catcode`\^^\=\other
+ \catcode`\^^]=\other
+ \catcode`\^^^=\other
+ \catcode`\^^_=\other
+ \catcode`\@=\other
+ \catcode`\^=\other
+ % It was suggested to define this as 7, which would allow ^^e4 etc.
+ % in xref tags, i.e., node names. But since ^^e4 notation isn't
+ % supported in the main text, it doesn't seem desirable. Furthermore,
+ % that is not enough: for node names that actually contain a ^
+ % character, we would end up writing a line like this: 'xrdef {'hat
+ % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first
+ % argument, and \hat is not an expandable control sequence. It could
+ % all be worked out, but why? Either we support ^^ or we don't.
+ %
+ % The other change necessary for this was to define \auxhat:
+ % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter
+ % and then to call \auxhat in \setq.
+ %
+ \catcode`\~=\other
+ \catcode`\[=\other
+ \catcode`\]=\other
+ \catcode`\"=\other
+ \catcode`\_=\other
+ \catcode`\|=\other
+ \catcode`\<=\other
+ \catcode`\>=\other
+ \catcode`\$=\other
+ \catcode`\#=\other
+ \catcode`\&=\other
+ \catcode`+=\other % avoid \+ for paranoia even though we've turned it off
+ % Make the characters 128-255 be printing characters
+ {%
+ \count 1=128
+ \def\loop{%
+ \catcode\count 1=\other
+ \advance\count 1 by 1
+ \ifnum \count 1<256 \loop \fi
+ }%
+ }%
+ % The aux file uses ' as the escape (for now).
+ % Turn off \ as an escape so we do not lose on
+ % entries which were dumped with control sequences in their names.
+ % For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+ % Reference to such entries still does not work the way one would wish,
+ % but at least they do not bomb out when the aux file is read in.
+ \catcode`\{=1
+ \catcode`\}=2
+ \catcode`\%=\other
+ \catcode`\'=0
+ \catcode`\\=\other
+ %
+ \openin 1 \jobname.aux
+ \ifeof 1 \else
+ \closein 1
+ \input \jobname.aux
+ \global\havexrefstrue
+ \global\warnedobstrue
+ \fi
+ % Open the new aux file. TeX will close it automatically at exit.
+ \openout\auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed. (Generally, numeric constants should always be followed by a
+% space to prevent strange expansion errors.)
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only.
+\let\footnotestyle=\comment
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+%
+% Auto-number footnotes. Otherwise like plain.
+\gdef\footnote{%
+ \global\advance\footnoteno by \@ne
+ \edef\thisfootno{$^{\the\footnoteno}$}%
+ %
+ % In case the footnote comes at the end of a sentence, preserve the
+ % extra spacing after we do the footnote number.
+ \let\@sf\empty
+ \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+ %
+ % Remove inadvertent blank space before typesetting the footnote number.
+ \unskip
+ \thisfootno\@sf
+ \footnotezzz
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter. Our footnotes don't need to be so general.
+%
+% Oh yes, they do; otherwise, @ifset and anything else that uses
+% \parseargline fail inside footnotes because the tokens are fixed when
+% the footnote is read. --karl, 16nov96.
+%
+\long\gdef\footnotezzz{\insert\footins\bgroup
+ % We want to typeset this text as a normal paragraph, even if the
+ % footnote reference occurs in (for example) a display environment.
+ % So reset some parameters.
+ \interlinepenalty\interfootnotelinepenalty
+ \splittopskip\ht\strutbox % top baseline for broken footnotes
+ \splitmaxdepth\dp\strutbox
+ \floatingpenalty\@MM
+ \leftskip\z@skip
+ \rightskip\z@skip
+ \spaceskip\z@skip
+ \xspaceskip\z@skip
+ \parindent\defaultparindent
+ %
+ % Hang the footnote text off the number.
+ \hang
+ \textindent{\thisfootno}%
+ %
+ % Don't crash into the line above the footnote text. Since this
+ % expands into a box, it must come within the paragraph, lest it
+ % provide a place where TeX can split the footnote.
+ \footstrut
+ \futurelet\next\fo@t
+}
+\def\fo@t{\ifcat\bgroup\noexpand\next \let\next\f@@t
+ \else\let\next\f@t\fi \next}
+\def\f@@t{\bgroup\aftergroup\@foot\let\next}
+\def\f@t#1{#1\@foot}
+\def\@foot{\strut\egroup}
+
+}%end \catcode `\@=11
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly. There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.08333}
+\def\strutheightpercent{.70833}
+\def\strutdepthpercent {.29167}
+%
+\def\setleading#1{%
+ \normalbaselineskip = #1\relax
+ \normallineskip = \lineskipfactor\normalbaselineskip
+ \normalbaselines
+ \setbox\strutbox =\hbox{%
+ \vrule width0pt height\strutheightpercent\baselineskip
+ depth \strutdepthpercent \baselineskip
+ }%
+}
+
+% @| inserts a changebar to the left of the current line. It should
+% surround any changed text. This approach does *not* work if the
+% change spans more than two lines of output. To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+ % \vadjust can only be used in horizontal mode.
+ \leavevmode
+ %
+ % Append this vertical mode material after the current line in the output.
+ \vadjust{%
+ % We want to insert a rule with the height and depth of the current
+ % leading; that is exactly what \strutbox is supposed to record.
+ \vskip-\baselineskip
+ %
+ % \vadjust-items are inserted at the left edge of the type. So
+ % the \llap here moves out into the left-hand margin.
+ \llap{%
+ %
+ % For a thicker or thinner bar, change the `1pt'.
+ \vrule height\baselineskip width1pt
+ %
+ % This is the space between the bar and the text.
+ \hskip 12pt
+ }%
+ }%
+}
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+% @image. We use the macros from epsf.tex to support this.
+% If epsf.tex is not installed and @image is used, we complain.
+%
+% Check for and read epsf.tex up front. If we read it only at @image
+% time, we might be inside a group, and then its definitions would get
+% undone and the next image would fail.
+\openin 1 = epsf.tex
+\ifeof 1 \else
+ \closein 1
+ % Do not bother showing banner with post-v2.7 epsf.tex (available in
+ % doc/epsf.tex until it shows up on ctan).
+ \def\epsfannounce{\toks0 = }%
+ \input epsf.tex
+\fi
+%
+% We will only complain once about lack of epsf.tex.
+\newif\ifwarnednoepsf
+\newhelp\noepsfhelp{epsf.tex must be installed for images to
+ work. It is also included in the Texinfo distribution, or you can get
+ it from ftp://tug.org/tex/epsf.tex.}
+%
+\def\image#1{%
+ \ifx\epsfbox\undefined
+ \ifwarnednoepsf \else
+ \errhelp = \noepsfhelp
+ \errmessage{epsf.tex not found, images will be ignored}%
+ \global\warnednoepsftrue
+ \fi
+ \else
+ \imagexxx #1,,,\finish
+ \fi
+}
+%
+% Arguments to @image:
+% #1 is (mandatory) image filename; we tack on .eps extension.
+% #2 is (optional) width, #3 is (optional) height.
+% #4 is just the usual extra ignored arg for parsing this stuff.
+\def\imagexxx#1,#2,#3,#4\finish{%
+ \ifx\pdfoutput\undefined
+ % \epsfbox itself resets \epsf?size at each figure.
+ \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi
+ \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi
+ \begingroup
+ \catcode`\^^M = 5 % in case we're inside an example
+ % If the image is by itself, center it.
+ \ifvmode
+ \nobreak\bigskip
+ % Usually we'll have text after the image which will insert
+ % \parskip glue, so insert it here too to equalize the space
+ % above and below.
+ \nobreak\vskip\parskip
+ \nobreak
+ \centerline{\epsfbox{#1.eps}}%
+ \bigbreak
+ \else
+ % In the middle of a paragraph, no extra space.
+ \epsfbox{#1.eps}%
+ \fi
+ \endgroup
+ \else
+ \centerline{\pdfimage #1.pdf}%
+ \fi
+}
+
+
+\message{localization,}
+% and i18n.
+
+% @documentlanguage is usually given very early, just after
+% @setfilename. If done too late, it may not override everything
+% properly. Single argument is the language abbreviation.
+% It would be nice if we could set up a hyphenation file here.
+%
+\def\documentlanguage{\parsearg\dodocumentlanguage}
+\def\dodocumentlanguage#1{%
+ \tex % read txi-??.tex file in plain TeX.
+ % Read the file if it exists.
+ \openin 1 txi-#1.tex
+ \ifeof1
+ \errhelp = \nolanghelp
+ \errmessage{Cannot read language file txi-#1.tex}%
+ \let\temp = \relax
+ \else
+ \def\temp{\input txi-#1.tex }%
+ \fi
+ \temp
+ \endgroup
+}
+\newhelp\nolanghelp{The given language definition file cannot be found or
+is empty. Maybe you need to install it? In the current directory
+should work if nowhere else does.}
+
+
+% @documentencoding should change something in TeX eventually, most
+% likely, but for now just recognize it.
+\let\documentencoding = \comment
+
+
+% Page size parameters.
+%
+\newdimen\defaultparindent \defaultparindent = 15pt
+
+\chapheadingskip = 15pt plus 4pt minus 2pt
+\secheadingskip = 12pt plus 3pt minus 2pt
+\subsecheadingskip = 9pt plus 2pt minus 2pt
+
+% Prevent underfull vbox error messages.
+\vbadness = 10000
+
+% Don't be so finicky about underfull hboxes, either.
+\hbadness = 2000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything. We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize. We call this whenever the paper size is set.
+%
+\def\setemergencystretch{%
+ \ifx\emergencystretch\thisisundefined
+ % Allow us to assign to \emergencystretch anyway.
+ \def\emergencystretch{\dimen0}%
+ \else
+ \emergencystretch = .15\hsize
+ \fi
+}
+
+% Parameters in order: 1) textheight; 2) textwidth; 3) voffset;
+% 4) hoffset; 5) binding offset; 6) topskip. Then whoever calls us can
+% set \parskip and call \setleading for \baselineskip.
+%
+\def\internalpagesizes#1#2#3#4#5#6{%
+ \voffset = #3\relax
+ \topskip = #6\relax
+ \splittopskip = \topskip
+ %
+ \vsize = #1\relax
+ \advance\vsize by \topskip
+ \outervsize = \vsize
+ \advance\outervsize by 2\topandbottommargin
+ \pageheight = \vsize
+ %
+ \hsize = #2\relax
+ \outerhsize = \hsize
+ \advance\outerhsize by 0.5in
+ \pagewidth = \hsize
+ %
+ \normaloffset = #4\relax
+ \bindingoffset = #5\relax
+ %
+ \parindent = \defaultparindent
+ \setemergencystretch
+}
+
+% @letterpaper (the default).
+\def\letterpaper{{\globaldefs = 1
+ \parskip = 3pt plus 2pt minus 1pt
+ \setleading{13.2pt}%
+ %
+ % If page is nothing but text, make it come out even.
+ \internalpagesizes{46\baselineskip}{6in}{\voffset}{.25in}{\bindingoffset}{36pt}%
+}}
+
+% Use @smallbook to reset parameters for 7x9.5 (or so) format.
+\def\smallbook{{\globaldefs = 1
+ \parskip = 2pt plus 1pt
+ \setleading{12pt}%
+ %
+ \internalpagesizes{7.5in}{5.in}{\voffset}{.25in}{\bindingoffset}{16pt}%
+ %
+ \lispnarrowing = 0.3in
+ \tolerance = 700
+ \hfuzz = 1pt
+ \contentsrightmargin = 0pt
+ \deftypemargin = 0pt
+ \defbodyindent = .5cm
+ %
+ \let\smalldisplay = \smalldisplayx
+ \let\smallexample = \smalllispx
+ \let\smallformat = \smallformatx
+ \let\smalllisp = \smalllispx
+}}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{{\globaldefs = 1
+ \setleading{12pt}%
+ \parskip = 3pt plus 2pt minus 1pt
+ %
+ \internalpagesizes{53\baselineskip}{160mm}{\voffset}{4mm}{\bindingoffset}{44pt}%
+ %
+ \tolerance = 700
+ \hfuzz = 1pt
+}}
+
+% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin
+% 29mm, hence bottom margin 28mm, nominal side margin 3cm.
+\def\afourlatex{{\globaldefs = 1
+ \setleading{13.6pt}%
+ %
+ \afourpaper
+ \internalpagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm}%
+ %
+ \globaldefs = 0
+}}
+
+% Use @afourwide to print on European A4 paper in wide format.
+\def\afourwide{%
+ \afourpaper
+ \internalpagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}%
+ %
+ \globaldefs = 0
+}
+
+% @pagesizes TEXTHEIGHT[,TEXTWIDTH]
+% Perhaps we should allow setting the margins, \topskip, \parskip,
+% and/or leading, also. Or perhaps we should compute them somehow.
+%
+\def\pagesizes{\parsearg\pagesizesxxx}
+\def\pagesizesxxx#1{\pagesizesyyy #1,,\finish}
+\def\pagesizesyyy#1,#2,#3\finish{{%
+ \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi
+ \globaldefs = 1
+ %
+ \parskip = 3pt plus 2pt minus 1pt
+ \setleading{13.2pt}%
+ %
+ \internalpagesizes{#1}{\hsize}{\voffset}{\normaloffset}{\bindingoffset}{44pt}%
+}}
+
+% Set default to letter.
+%
+\letterpaper
+
+
+\message{and turning on texinfo input format.}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\catcode`\$=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+\def\normaldollar{$}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise. Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi}
+
+% Same as above, but check for italic font. Actually this also catches
+% non-italic slanted fonts since it is impossible to distinguish them from
+% italic fonts. But since this is only used by $ and it uses \sl anyway
+% this is not a problem.
+\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt\char34}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt\char126}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+\catcode`\|=\active
+\def|{{\tt\char124}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+\catcode`\$=\active
+\def${\ifusingit{{\sl\$}}\normaldollar}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`+=\active
+\catcode`\_=\active
+
+% If a .fmt file is being used, characters that might appear in a file
+% name cannot be active until we have parsed the command line.
+% So turn them off again, and have \everyjob (or @setfilename) turn them on.
+% \otherifyactive is called near the end of this file.
+\def\otherifyactive{\catcode`+=\other \catcode`\_=\other}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% \catcode 17=0 % Define control-q
+\catcode`\\=\active
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+@def@turnoffactive{@let"=@normaldoublequote
+@let\=@realbackslash
+@let~=@normaltilde
+@let^=@normalcaret
+@let_=@normalunderscore
+@let|=@normalverticalbar
+@let<=@normalless
+@let>=@normalgreater
+@let+=@normalplus
+@let$=@normaldollar}
+
+@def@normalturnoffactive{@let"=@normaldoublequote
+@let\=@normalbackslash
+@let~=@normaltilde
+@let^=@normalcaret
+@let_=@normalunderscore
+@let|=@normalverticalbar
+@let<=@normalless
+@let>=@normalgreater
+@let+=@normalplus
+@let$=@normaldollar}
+
+% Make _ and + \other characters, temporarily.
+% This is canceled by @fixbackslash.
+@otherifyactive
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+% Also back turn on active characters that might appear in the input
+% file name, in case not using a pre-dumped format.
+%
+@gdef@fixbackslash{%
+ @ifx\@eatinput @let\ = @normalbackslash @fi
+ @catcode`+=@active
+ @catcode`@_=@active
+}
+
+% Say @foo, not \foo, in error messages.
+@escapechar = `@@
+
+% These look ok in all fonts, so just make them not special.
+@catcode`@& = @other
+@catcode`@# = @other
+@catcode`@% = @other
+
+@c Set initial fonts.
+@textfonts
+@rm
+
+
+@c Local variables:
+@c eval: (add-hook 'write-file-hooks 'time-stamp)
+@c page-delimiter: "^\\\\message"
+@c time-stamp-start: "def\\\\texinfoversion{"
+@c time-stamp-format: "%:y-%02m-%02d.%H"
+@c time-stamp-end: "}"
+@c End:
diff --git a/Docs/To-be-included-in-the-manual/MySQL-for-dummies b/Docs/To-be-included-in-the-manual/MySQL-for-dummies
new file mode 100644
index 00000000000..7b669af18dc
--- /dev/null
+++ b/Docs/To-be-included-in-the-manual/MySQL-for-dummies
@@ -0,0 +1,271 @@
+===============================================================================
+installing/mysql/binary Fri Jul 17 13:03:03 1998 has
+===============================================================================
+
+ MySQL for dummies - Part 1
+ How to get the binary distribution running on a UNIX system
+
+ MySQL is a trademark of TcX, Sweden.
+
+===============================================================================
+
+Introduction:
+
+This is a simple cookbook for the helpless newbie taking his very first steps
+with MySQL, when he needs a few hints about the options and access rights
+installing the system and starting the basic modules, before he has "aha"ed
+on how simple and clean the basic structure of MySQL is. It will not help
+you with the intricacies and subtle possibilities of SQL as implemented in
+MySQL.
+
+The information in this document is all contained in the MySQL manual in a
+more or less obvious form, but for the newbie that document is a bit over-
+whelming in size, and it contains some new concepts that take some getting
+used to. Sorry if it is pitched too low for some readers. It is only
+intended to get the binary distribution up and running.
+
+I successfully got MySQL going on both a Sun SparcStation 1 running SunOS 4.1.2
+and 2 Linux systems running SuSE release 5.0, one with kernel version 2.0.30,
+one with 2.0.33 by doing exactly what is given here. If it doesn't work
+for you, I suggest the problem is with your system and not with the
+MySQL binary distribution.
+
+-- Howard Schultens hs@neuro-physiol.med.uni-goettingen.de
+
+-------------------------------------------------------------------------------
+
+Nomenclature:
+
+In the following, 'MySQL' refers to the entire database system distributed
+and licensed by TcX. 'mysql' means a specific program in this system.
+
+-------------------------------------------------------------------------------
+
+MySQL user administration and access rights ("privileges"):
+
+It is obvious that MySQL needs its own user management because it is a system
+that is implemented on a number of architectures -- you should be able to use
+it in an identical way on different operating systems. The MySQL user names
+and passwords have basically nothing at all to do with user names and
+passwords on whatever operating system you install it on. You will,
+unfortunately, have to install your users again on MySQL. But this system has
+some big advantages: it is a secure system that allows you to finely
+differentiate access rights based on WHO is using a database from WHERE. It
+does this by the use of its own database containing 3 tables "user" for the
+user names, "db" for the databases, and "host" for the machines that access
+databases. "user" and "db" are the most important for the newbie.
+
+Section 6 of the manual describes all this in detail.
+
+-------------------------------------------------------------------------------
+
+Doing it:
+
+In the following, "foo>" denotes the prompt from your system in user mode,
+"foo#" as root/superuser.
+
+
+1) Get the appropriate binary distribution from a mirror site or directly
+ from TcX at URL http://www.tcx.se. The file name has the form
+ mysql-VERSION-SYSTEM.tgz
+
+ VERSION = Version number, e.g. 3.21.33
+ SYSTEM = OS and architecture, e.g. sunos4.1.4-sparc
+
+ i.e., you would download a file mysql-3.21.33-sunos4.1.4-sparc.tgz.
+
+ This example is for SunOS, but it works exactly analogously on Linux.
+
+2) cd to /usr/local and unpack this with, e.g. the command
+
+ foo#gzip -c -d mysql-VERSION-SYSTEM.tgz|tar xvf -
+
+3) The files are stored in a directory /usr/local/mysql-VERSION-SYSTEM
+ Make a symbolic link to this directory:
+
+ foo#ln -s mysql-VERSION-SYSTEM mysql
+
+ At this point, you might want to create a special user for all your
+ MySQL stuff. I use "mysql". Then you could do
+
+ foo#chown -R mysql mysql-VERSION-SYSTEM
+
+4) FIRST, take care of all the PERL stuff:
+
+ o) You need PERL 5.004 or later already installed on your system. Take
+ care of this first if necessary.
+
+ a) cd to /usr/local/mysql/perl/DBI and do
+ foo#perl Makefile.PL
+ foo#make
+ foo#make test
+ foo#make install (if "make test" is successful)
+
+ b) cd to /usr/local/mysql/perl/Mysql/modules and do
+ foo#perl Makefile.PL
+ foo#make
+ foo#make test
+ foo#make install (if "make test" is successful)
+
+ c) As an option, you can install Data::ShowTable, but this is not absolutely
+ necessary for mysql. Get the PERL module Data-ShowTable-VER.tar.gz
+ (VER = version, eg. 3.3) from a CPAN mirror: I got mine at
+
+ ftp://ftp.gwdg.de/pub/languages/perl/CPAN/modules/by-category/06_Data_Type_Utilities/Data/Data-ShowTable-3.3.tar.gz
+
+ (You should be able to replace "ftp.gwdg.de" by the name of another
+ FTP mirror)
+
+ Put this into /usr/local/mysql/perl and unpack it.
+ You get a directory 'Data-ShowTable-VER'. cd into there and
+ (as root/superuser)
+ foo#perl Makefile.PL
+ foo#make
+ foo#make test
+ foo#make install (if "make test" is successful)
+
+5) cd to /usr/local/mysql and do
+ foo#scripts/mysql_install_db
+
+ you should be in /usr/local/mysql when you start the script.
+
+==>*NOTE* you might want to edit this script before you run it the first
+ time. See method 9b) below.
+
+ If this is successful, one or more copies of the mysql daemon, mysqld,
+ will be running. On SunOS 4.1.x, you get one. On Linux, 3 are running.
+
+-------------------------------------------------------------------------------
+In the rest of this, I will always suppose you are starting in the directory
+/usr/local/mysql, even if it seems mildly inconvenient
+-------------------------------------------------------------------------------
+
+6) You can now select the database 'test' and mess around with it using
+ the client program bin/mysql: start it with
+
+ foo>bin/mysql -u root test
+
+ This says, "start up the MySQL command-line client with the user name
+ 'root' and use the database named 'test', which is a subdirectory in
+ '/usr/local/mysql/data". (n.b. this is NOT the root user of your UNIX
+ system, it is a MySQL user with the same name. You will notice that you
+ don't need a password for this user to use mysql).
+
+ Actually, the way the system is set up by bin/mysql_install_db, you
+ don't even need a user name to access the database 'test'. You can start
+ the client simply with
+
+ foo>bin/mysql test
+
+ 'mysql' should start up with a greeting and a line telling you what your
+ connection id and server version is. At this point, the database 'test'
+ is empty, no tables or anything are defined.
+
+ When you issue SQL commands, DON'T FORGET THE FINAL SEMICOLON, or mysql acts
+ dumb:
+
+ mysql>select * from user
+ ->
+ ->
+
+ and you wonder what's going on. 'mysql' reminds you of this on startup.
+
+7) When you want to close down the server, do
+ foo>bin/mysqladmin shutdown
+
+8) I recommend editing the script bin/safe_mysqld for the binary release
+ so that it always starts up with the correct directories. I replaced
+ the entire header up to but not including
+
+ pidfile=$DATADIR/`/bin/hostname`.pid
+ log=$DATADIR/`/bin/hostname`.log
+ err=$DATADIR/`/bin/hostname`.err
+
+ with
+
+ MY_BASEDIR_VERSION=/usr/local/mysql
+ DATADIR=$MY_BASEDIR_VERSION/data
+ ledir=$MY_BASEDIR_VERSION/bin
+ cd $MY_BASEDIR_VERSION
+
+ This lets you start the mysql daemon from wherever you like.
+
+9) Now let's say you want to put some of your own databases and users into
+ the system. The simplest, most powerful, and dangerous way to do this is
+ to start up the mysql daemon again with:
+
+ foo>bin/mysqld --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data -Sg
+
+ This skips loading the grant tables. The system is open to every kind of
+ mistake now, so be careful. Any user can muck up the grant tables, ie.
+ the lists of users, hosts, and databases themselves, so only use this
+ mode to do these first, very basic things.
+
+ Start the client again now, with
+ foo>bin/mysql mysql
+
+ This tells the client to use the database 'mysql', which is the directory
+ that contains the lists (ie. the tables) of all the users, hosts, and
+ databases in the system, so be careful!!!!!!!!!!!!
+
+ All of what follows is taken essentially from section 6 of the manual.
+
+ a) For the start, just define a couple of users for the MySQL system:
+ i) an administrator, such as 'mysql', with its own password, that
+ can do everything with the system:
+
+ mysql> insert into user values('localhost','mysql',password('xyzzy'),
+ 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
+
+ * For some reason, on my Linux system with a German keyboard, I have *
+ * to use the acute accent instead of the apostrophe, otherwise I get *
+ * parse errors. *
+
+ This defines the user name 'mysql' with password 'xyzzy' that can
+ do everything. To look at what you just did, type in
+
+ mysql> select * from user;
+
+ mysql types out a table with all the known users and their privileges.
+
+ ii) a privileged user for playing around:
+
+ mysql> insert into user values('localhost','john',password('blah0x1'),
+ 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
+
+ iii) create your own database for a todo list, phone numbers, whatever:
+
+ mysql> create database johns_DB;
+ mysql> insert into db values('localhost','johns_DB','john','Y','Y','Y','Y','Y','Y');
+
+ The first line creates the databse "johns_DB", but that doesn't
+ make it visible to mysql. The second line does that.
+
+ iv) When you are done installing users and databases, quit mysql and
+ issue the command
+
+ foo>bin/mysqladmin reload
+
+ b) Another method to do this was suggested by Sinisa Milivojevic, and that
+ is to edit the script /usr/local/mysql/scripts/mysql_install_db to
+ define the databases and install the more important users when you
+ start the system the very first time. This would have the advantage
+ that you can save the script and re-install the system with it if you
+ have to, automatically defining the important structures. It requires
+ a little more knowledge of the MySQL system to do this.
+
+ You might want to use this method anyway since it saves editing
+ mysql_install_db to have it install a superuser with a name other
+ than "root". The places to change are easy to find. You can, of
+ course, use the first method above and remove the user named 'root'
+ when you are done.
+
+
+===============================================================================
+
+If anyone is interested enough in this document to make suggestions on how
+to improve it, I would be glad to get emails on it. I hope it helps
+someone get going with MySQL a little easier.
+
+--Howard
+ hs@neuro-physiol.med.uni-goettingen.de
diff --git a/Docs/Translations/myodbc-br.texi b/Docs/Translations/myodbc-br.texi
new file mode 100644
index 00000000000..6cf7edd3e75
--- /dev/null
+++ b/Docs/Translations/myodbc-br.texi
@@ -0,0 +1,272 @@
+@chapter MySQL ODBC Suporte
+
+@menu
+* Quais ODBC OS:: Sistemas Operacionais são suportados por @strong{MyODBC}
+* Problemas ODBC:: Como informar problemas com @strong{MySQL} ODBC
+* Clientes MyODBC:: Programas que já foram testados com @strong{MyODBC}
+* Administrador ODBC:: Como preencher os diversos campos com o programa Administrador
+* ODBC e last_insert_id:: Como obter o valor de uma coluna @code{AUTO_INCREMENT} em ODBC
+* Informando bug do MyODBC:: Informando problemas com MyODBC
+@end menu
+
+@strong{MySQL} fornece suporte para ODBC através do programa @strong{MyODBC}.
+
+
+@node Quais ODBC OS, ODBC Problemas, ODBC, ODBC
+@section Sistemas Operacionais suportados por MyODBC
+
+@strong{MyODBC} é um driver 32-bit ODBC (2.50) nível 0 para Windows95
+e Windows NT. Nós esperamos que alguém porte o mesmo para o Windows 3.x.
+
+@node Problemas ODBC, clientes MyODBC, Quais ODBC OS, ODBC
+@section Como informar problemas com MyODBC
+
+@strong{MyODBC} tem sido testado com Access, Admndemo.exe, C++-Builder,
+Centura Team Developer (formalmente Gupta SQL/Windows), ColdFusion (no
+Solaris e NT com svc pack 5), Crystal Reports, DataJunction, Delphi,
+ERwin, Excel, iHTML, FileMaker Pro, FoxPro, Notes 4.5/4.6, SBSS, Perl
+DBD-ODBC, Paradox, Powerbuilder, Powerdesigner 32 bit, VC++ e Visual
+Basic.
+
+Se você souber de algum outro aplicativo que funcione com @strong{MyODBC}, por favor
+nos escreva sobre isso através do email @email{myodbc@@lists.mysql.com}.
+
+@node Clientes MyODBC, Administrador ODBC, Problemas com ODBC, ODBC
+@section Programas testados que funcionam com MyODBC
+
+A maioria dos programas que têm suporte para ODBC, funcionam com o @strong{MyODBC},
+mas cada um dos listados abaixo, têm sido testados por nós ou por informações de
+usuários que confirmaram o seu funcionamento.
+
+@table @asis
+@item @strong{Program}
+@strong{Comment}
+@item Access
+Como fazer Accces funcionar:
+@itemize @bullet
+@item
+Você deverá ter uma chave primária na tabela.
+@item
+Você deve ter um campo timestamp em todas as tabelas em que você quer controlar a
+atualização.
+
+@item
+Somente use campos doubles float. Access falha quando faz comparações com campos float
+simples.
+@item
+Configure a opção `Return matching rows' quando conectar com o @strong{MySQL}.
+@item
+O Access no NT acusará colunas @code{BLOB} como @code{OLE OBJECTS}.
+Se ao invés disso você quer colunas @code{MEMO}, deve trocar a coluna para
+@code{TEXT} usando @code{ALTER TABLE}.
+@item
+Access às vezes não lida adequadamente com colunas do tipo @code{DATE}.
+Se você tiver problemas com essas colunas, mude as colunas para @code{DATETIME}.
+@item
+Em certas situações, o Access cria consultas SQL ilegais que o
+@strong{MySQL} não pode processar. Você pode resolver isso selecionando o tipo de
+consulta @code{"Query|SQLSpecific|Pass-Through"} no menu do Access.
+@end itemize
+@item DataJunction
+Você tem que trocar para mandar @code{VARCHAR} ao invés de @code{ENUM}, porque
+o mesmo exporta o último de uma maneira que causa fadiga ao @strong{MySQL}.
+@item Excel
+Funciona. Algumas dicas:
+@itemize @bullet
+@item
+Se você tem problemas com datas, tente selecioná-las como strings usando a
+função @code{CONCAT()}. Por exemplo:
+@example
+select CONCAT(rise_time), CONCAT(set_time)
+ from sunrise_sunset;
+@end example
+Os dados de datas enviadas como string são corretamente reconhecidas pelo
+Excel97 como dados do tipo time.
+
+Neste exemplo o propósito de @code{CONCAT()} é enganar o ODBC, fazendo-o pensar
+que a coluna é do 'tipo string'. Sem o @code{CONCAT()}, ODBC sabe que a coluna
+é do tipo time e o Excel não entenderá isso.
+
+Note que isso é um bug no Excel, porque o mesmo converte automaticamente a
+string para time. Isto é muito bom quando o fonte é um arquivo
+texto, mas não se pode dizer o mesmo quando o fonte é uma conexão
+ODBC que informa o tipo exato para cada coluna.
+@end itemize
+@item odbcadmin
+Programa Teste para ODBC.
+@item Delphi
+Você deverá usar DBE 3.2 ou mais atualizado. Configure o campo de opção
+`Don't optimize column width' quando conectando com @strong{MySQL}.
+
+Também, há aqui um código muito útil que configura tanto a
+inserção ODBC e a inserção BDE para MyODBC (a inserção BDE requer um BDE
+Alias Editor que pode ser obtido de graça numa Delphi Super Page
+perto de você.): (Obrigado a Bryan Brunton @email{bryan@@flesherfab.com} por isto)
+
+@example
+fReg:= TRegistry.Create;
+ fReg.OpenKey('\Software\ODBC\ODBC.INI\DocumentsFab', True);
+ fReg.WriteString('Database', 'Documents');
+ fReg.WriteString('Description', ' ');
+ fReg.WriteString('Driver', 'C:\WINNT\System32\myodbc.dll');
+ fReg.WriteString('Flag', '1');
+ fReg.WriteString('Password', '');
+ fReg.WriteString('Port', ' ');
+ fReg.WriteString('Server', 'xmark');
+ fReg.WriteString('User', 'winuser');
+ fReg.OpenKey('\Software\ODBC\ODBC.INI\ODBC Data Sources', True);
+ fReg.WriteString('DocumentsFab', 'MySQL');
+ fReg.CloseKey;
+ fReg.Free;
+
+ Memo1.Lines.Add('DATABASE NAME=');
+ Memo1.Lines.Add('USER NAME=');
+ Memo1.Lines.Add('ODBC DSN=DocumentsFab');
+ Memo1.Lines.Add('OPEN MODE=READ/WRITE');
+ Memo1.Lines.Add('BATCH COUNT=200');
+ Memo1.Lines.Add('LANGDRIVER=');
+ Memo1.Lines.Add('MAX ROWS=-1');
+ Memo1.Lines.Add('SCHEMA CACHE DIR=');
+ Memo1.Lines.Add('SCHEMA CACHE SIZE=8');
+ Memo1.Lines.Add('SCHEMA CACHE TIME=-1');
+ Memo1.Lines.Add('SQLPASSTHRU MODE=SHARED AUTOCOMMIT');
+ Memo1.Lines.Add('SQLQRYMODE=');
+ Memo1.Lines.Add('ENABLE SCHEMA CACHE=FALSE');
+ Memo1.Lines.Add('ENABLE BCD=FALSE');
+ Memo1.Lines.Add('ROWSET SIZE=20');
+ Memo1.Lines.Add('BLOBS TO CACHE=64');
+ Memo1.Lines.Add('BLOB SIZE=32');
+
+ AliasEditor.Add('DocumentsFab','MySQL',Memo1.Lines);
+@end example
+
+@item C++Builder
+Testado com BDE 3.0. O único problema conhecido é que quando o esquema da tabela
+muda, os campos da consulta não são atualizados. BDE entretanto, parece não
+reconhecer chaves primárias, somente Índice PRIMARY, não entanto isto não
+tem sido um problema.
+
+@item Visual basic
+Para atualizar uma tabela, você deverá definir uma chave primária para a tabela.
+@end table
+
+@node Administrador ODBC, ODBC e last_insert_id, Clientes MyODBC, ODBC
+@section Como preencher os diversos campos com o programa Administrador
+
+Existem três possibilidades para especificar o nome do servidor em
+Windows95:
+
+@itemize @bullet
+@item
+Usando o endereço IP do servidor.
+@item
+Adicionar um arquivo @file{lmhosts} com a seguinte informação:
+
+@example
+ip nomeservidor
+@end example
+
+Por exemplo:
+
+@example
+194.216.84.21 my
+@end example
+
+@item
+Configurar o PC para usar DNS.
+@end itemize
+
+Exemplo de como preencher o ``ODBC setup'':
+@example
+Windows DSN name: teste
+Description: Este é o meu banco de dados teste
+MySql Database: teste
+Server: 194.216.84.21
+User: monty
+Password: minha_senha
+Port:
+@end example
+
+O valor para o campo @code{Windows DSN name} é qualquer nome que seja único
+em seu Windows ODBC setup.
+
+Você não precisa especificar os valores para os seguintes campos: @code{Server},
+@code{User}, @code{Password} ou @code{Port} na hora de configurar o ODBC.
+Entretanto, se você o faz, esses valores devem ser usados como padrão para fazer
+uma conexão. Você tem a opção de trocar os valores nesse instante.
+
+Se o número da porta não for especificado, o valor padrão da porta (@value{default_port})
+é usado.
+
+Se você especificar a opção @code{Read options from C:\my.cnf}, os
+grupos @code{client} e @code{odbc} devem ser lidos do arquivo @file{C:\my.cnf}.
+Você pode usar todas as opções que são usadas por @code{mysql_options()}.
+@xref{mysql_options, , @code{mysql_options}}.
+
+@node ODBC e last_insert_id, Informando bug do MyODBC, Administrador ODBC, ODBC
+@section Como obter o valor de uma coluna @code{AUTO_INCREMENT} no ODBC
+
+Um problema muito usual consiste em como saber o valor de uma coluna do tipo
+@code{INSERT} quando a mesma é gerada automaticamente. Com ODBC, você pode
+fazer uma coisa como esta (assumindo que @code{auto} é um campo @code{AUTO_INCREMENT}):
+
+@example
+INSERT INTO foo (auto,text) VALUES(NULL,'text');
+SELECT LAST_INSERT_ID();
+@end example
+
+Ou se você somente quer adicionar o valor noutra tabela, faça o
+seguinte:
+
+@example
+INSERT INTO foo (auto,text) VALUES(NULL,'text');
+INSERT INTO foo2 (id,text) VALUES(LAST_INSERT_ID(),'text');
+@end example
+
+Para o benefício de algumas aplicações ODBC (pelo menos Delphi e Access),
+a seguinte consulta pode ser usada para encontrar o valor do novo registro
+adicionado:
+
+@example
+SELECT * FROM tbl_name WHERE auto IS NULL;
+@end example
+
+@node Informando bug do MyODBC, , ODBC e last_insert_id, ODBC
+@section Informando problemas com MyODBC
+
+Se você encontra dificuldades com MyODBC, deve começar por fazer
+um arquivo log no Administrador ODBC (o log você tem quando
+solicita logs do ODBCADMIN) e um log @strong{MyODBC}. Para gerar um log @strong{MyODBC},
+clique a opção `Trace MyODBC' na tela de configuração da conexão
+@strong{MyODBC}.
+O log será escrito no arquivo @file{C:\myodbc.log}.
+Note que você deve usar a @code{MYSQL.DLL} e não a
+@code{MYSQL2.DLL} para que esta opção funcione!
+
+Verifique as consultas que MyODBC envia para o servidor @strong{MySQL};
+Você deverá ser capaz de encontrar isto através da pesquisa da
+string @code{>mysql_real_query} no arquivo @file{myodbc.log}.
+
+Você deve também tentar duplicar as consultas no monitor @code{mysql}
+ou @code{admndemo} para encontrar se o erro é do MyODBC ou do @strong{MySQL}.
+
+Se você encontrar algo errado, por favor envie somente as linhas
+relevantes (máximo 40 linhas) para o @email{myodbc@@lists.mysql.com}. Favor nunca
+enviar os arquivos log completos do MyODBC ou do ODBC !
+
+Se você não encontra o quê está errado, a última opção
+é fazer um arquivo (tar ou zip) que contenha um arquivo log do MyODBC,
+o arquivo log ODBC e um arquivo README que explique o problema.
+Você o manda para @uref{ftp://www.mysql.com/pub/mysql/secret}. Somente nós da TCX
+devemos ter acesso a esses arquivos que você manda e nós seremos muito discretos com
+os dados !
+
+Se você pode fazer um programa que também mostre o mesmo problema, favor mandá-lo
+também!
+
+Se o programa funciona com outro servidor SQL, você pode fazer um
+arquivo log que faça exatamente a mesma coisa com o outro servidor
+SQL.
+
+Lembre que quanto mais informação você nos fornece, o resultado é
+que nós podemos resolver o problema!
diff --git a/Docs/Tutorial-MySQL-final.txt b/Docs/Tutorial-MySQL-final.txt
new file mode 100644
index 00000000000..bd52554a611
--- /dev/null
+++ b/Docs/Tutorial-MySQL-final.txt
@@ -0,0 +1,1643 @@
+8 Tutorial MySQL
+=======================
+
+Este capítulo ofrece un tutorial de introducción a MySQL, mostrando cómo usar el programa cliente
+mysql para crear y usar una simple base de datos. mysql (al que algunas veces nos referimos como
+"monitor terminal" o simplemente "monitor") es un programa interactivo que te permite conectarte a
+un servidor MySQL, ejecutar consultas y observar los resultados. mysql puede ser usado también en
+modo batch: escribes tus consultas en un fichero de texto, para después pedirle a mysql que
+ejecute el contenido del fichero. Se cubren aquí esas dos formas de usar de usar mysql.
+
+Para ver una lista de opciones proporcionadas por mysql, lánzalo con las opción --help :
+
+ shell> mysql --help
+
+Este capítulo asume que mysql está instalado en tu máquina, y que hay disponible un servidor al que
+te puedes conectar. Si esto no es así, contacta con tu administrador MySQL. (Si el administrador
+eres tú, necesitarás consultar otra sección de este manual).
+
+El capítulo describe el proceso completo de configurar y usar una base de datos. Si estás interesado
+sólo en acceder una base de datos ya existente, querrás saltar las secciones que describen cómo
+crear la base de datos y las tablas que la contienen.
+
+Dado que este capítulo es un tutorial básico, se dejarán en el tintero muchos
+detalles. Consulta las secciones relevantes del manual para más información sobre los temas
+aquí cubiertos.
+
+
+8.1 Conectando y desconectando del servidor
+=============================================
+
+
+Para conectarse al servidor, generalmente necesitarás facilitar un nombre de usuario MySQL cuando
+lances el cliente mysql y, lo más probable, también un password. Si el servidor se está ejecutando
+en una máquina distinta a la que estás conectado, necesitarás especificar también un nombre de
+host. Contacta con tu administrador para averiguar qué parámetros de conexión necesitas usar para
+conectar (es decir, qué host, nombre de usuario y password usar). Una vez que conozcas los
+parámetros adecuados, deberás ser capaz de conectar de la siguiente forma:
+
+shell> mysql -h host -u user -p
+Enter password: *******
+Welcome to the MySQL monitor. Commands end with ; or \g.
+Your MySQL connection id is 459 to server version: 3.22.20a-log
+
+Type 'help' for help.
+
+mysql>
+
+El prompt te indica que mysql ya está listo para la introducción de comandos.
+
+Algunas instalaciones MySQL permiten a los usuarios conectarse como usuarios "anonymous" (sin
+nombre) al servidor ejecutándose en el host local. Si este es el caso en tu máquina, deberías ser
+capaz de conectar a ese servidor invocando mysql sin ninguna opción:
+
+shell> mysql
+
+Una vez que hayas conectado con éxito, puedes desconectarte en cualquier momento tecleando QUIT en
+el prompt mysql> :
+
+mysql> QUIT
+Bye
+
+También puedes desconectar tecleando control-D.
+
+La mayor parte de los ejemplos en las siguientes secciones asumen que estás conectado al
+servidor. Lo indicarán por el prompt mysql>
+
+
+8.2 Haciendo consultas
+========================
+
+Asegúrate de que estás conectado al servidor, como se ha discutido en secciones anteriores. El
+hacerlo no implica que tengas seleccionada ninguna base de datos con la que trabajar, pero está
+bien. En este punto, es más importante averiguar un poco sobre cómo lanzar consultas que lanzarse
+directamente a la creación de tablas, cargar datos en ellas y recuperar los datos de las
+mismas. Esta sección describe los principios básicos de la entrada de comandos, usando varias
+consultas que puedes probar para familiarizarte con la forma de trabajo de mysql.
+
+Aquí presentamos un comando simple que pide al servidor que nos diga su número de versión y fecha
+actual. Tecléalo como se muestra a continuación siguiendo el prompt mysql> y pulsa la tecla RETURN:
+
+
+mysql> SELECT VERSION(), CURRENT_DATE;
++-----------+--------------+
+| version() | CURRENT_DATE |
++-----------+--------------+
+| 3.22.23b | 2000-01-05 |
++-----------+--------------+
+1 row in set (0.06 sec)
+
+mysql>
+
+Esta consulta ilustra muchas cosas sobre mysql:
+
+* Un comando consiste normalmente de una sentencia SQL seguida por un punto y coma. (Existen algunas
+ excepciones donde no es necesario el punto y coma. QUIT, mencionado más adelante, es una de
+ ellas. Conoceremos otras más adelante.)
+
+* Cuando lanzas un comando, mysql lo envía al servidor para su ejecución y muestra los resultados,
+ después imprime otro mysql> para indicar que está listo para otro comando.
+
+* mysql muestra la salida de una consulta como una tabla (filas y columnas). La primera fila
+ contiene etiquetas para las columnas. Las siguientes filas son el resultado de la
+ consulta. Normalmente, las etiquetas de las columnas son los nombres de las columnas que has
+ obtenido de la base de datos. Si pides el valor de una expresión en vez de una columna de una
+ tabla (como en el ejemplo anterior), mysql etiqueta la columna usando la propia expresión.
+
+* mysql muestra el número de filas que se han dado como resultado, y cuánto tiempo llevó la
+ ejecución de la consulta, lo que te da una idea aproximada del rendimiento del servidor. Estos
+ valores son imprecisos porque representan tiempo real (no tiempo de CPU o máquina), y porque están
+ afectados por factores como la carga del servidor y la latencia de la red. (Por cuestiones de
+ brevedad, la línea "rows in set" no se mostrará en los ejemplos posteriores de este capítulo.)
+
+Las palabras clave pueden ser tecleadas en cualquier combinación mayúscula/minúscula. Las siguientes
+consultas son equivalentes:
+
+mysql> SELECT VERSION(), CURRENT_DATE;
+mysql> select version(), current_date;
+mysql> SeLeCt vErSiOn(), current_DATE;
+
+He aquí otra consulta. Demuestra que puedes usar mysql como una calculadora sencilla:
+
+mysql> SELECT SIN(PI()/4), (4+1)*5;
++-------------+---------+
+| SIN(PI()/4) | (4+1)*5 |
++-------------+---------+
+| 0.707107 | 25 |
++-------------+---------+
+
+Los comandos vistos hasta aquí han sido relativamente cortos, sentencias de una sola línea. También puedes
+insertar múltiples sentencias en una sola línea. Simplemente, termina cada una con un punto y coma:
+
+mysql> SELECT VERSION(); SELECT NOW();
+
++-----------+
+| version() |
++-----------+
+| 3.22.23b |
++-----------+
+
++---------------------+
+| NOW() |
++---------------------+
+| 2000-01-05 17:33:16 |
++---------------------+
+
+Un comando no necesita ser dado todo en una sóla línea, así pues, los comandos largos que requieran
+varias lineas no son un problema. mysql determina cuando termina tu sentencia buscando el punto y
+coma final, no buscando el final de la línea de entrada. (En otras palabras, mysql acepta entrada de
+libre formato: recoleta las líneas de entrada pero no las ejecutahasta que vea el punto y coma.)
+
+Aquí tenemos un simple ejemplo de múltiples líneas:
+
+mysql> SELECT
+ -> USER()
+ -> ,
+ -> CURRENT_DATE;
++----------------+--------------+
+| USER() | CURRENT_DATE |
++----------------+--------------+
+| root@localhost | 2000-01-05 |
++----------------+--------------+
+
+En este ejemplo, observa como cambia el prompt de mysql> a -> una vez que has insertado la primera
+línea de una consulta multi-línea. Esta es la forma en que mysql indica que no ha encontrado una
+sentencia completa y que está esperando por el resto. El prompt es tu amigo, dado que ofrece una
+retroalimentación (feedback) significativa. Si usas ese feedback, siempre sabrás a qué está
+esperando mysql.
+
+Si decides que no quieres ejecutar un comando que está en proceso de introducción, puedes cancelarlo
+tecleando \c :
+
+mysql> SELECT
+ -> USER
+ -> \c
+mysql>
+
+Observa aquí también el prompt. Ha vuelto a mysql> tras haber tecleado \c, ofreciendo un feedback
+que indica que mysql está listo para un nuevo comando.
+
+La siguiente tabla muestra cada uno de los prompts que puedes ver y resume qué es lo que significan
+y el estado en el que se encontrará mysql:
+
+Prompt Significado
+mysql> Listo para un nuevo comando
+ -> Esperando una nueva línea de una consulta multi-línea
+ '> Esperando la siguiente línea, se ha insertado una línea que comienza con (')
+ "> Esperando la siguiente línea, se ha insertado una línea que comienza con (")
+
+Las sentencias multi-línea ocurren comúnmente "por accidente" cuando intentas lanzar un comando en
+una única línea, pero olvidas el punto y coma del final. En este caso, mysql espera más entrada:
+
+mysql> SELECT USER()
+ ->
+
+Si esto es lo que te ocurre (crees que has introducido una sentencia pero la única respuesta es un
+prompt como ->), lo más probable es que mysql esté esperando por el punto y coma. Si no observas qué
+es lo que te dice el prompt, podrías quedarte esperando un buen rato antes de enterarte de qué es lo
+que sucede. Introduce un punto y coma para completar la sentencia, y mysql la ejecutará:
+
+mysql> SELECT USER()
+ -> ;
++----------------+
+| USER() |
++----------------+
+| root@localhost |
++----------------+
+
+Los prompts '> y "> ocurren durante la recogida de strings. En MySQL, puedes escribir strings
+encerrados por comillas simples (') o dobles (") (por ejemplo, 'hola' o "adios"), y mysql te permite
+introducir también strings que se cortan en múltiples líneas. Cuando veas un prompt como '> ó ">,
+significa que has introducido una línea que contenía un string que comenzaba por (') o ("), pero que
+no has introducido aún la comilla (simple o doble) de cierre. Esto está bien si realmente estabas
+introduciendo un string multi-línea, pero no es lo más normal. Lo que sí es más normal, es que los
+prompts '> ó "> indiquen que te has olvidado del caracter de cierre " ó '. Por ejemplo:
+
+mysql> SELECT * FROM mi_tabla WHERE nombre ="García AND edad < 30;
+ ">
+
+Si tecleas esta sentencia SELECT, después pulsas ENTER y esperas por el resultado, no sucederá
+nada. En lugar de preocuparte, "¿por qué tarda tanto esta consulta?", observa la pista que te ofrece
+el prompt "> . Esto te indica que mysql espera ver el resto de un string que aún no ha
+terminado. (¿Ves el error en la sentencia? La cadena "García ha perdido las comillas de cierre.)
+
+Llegados a este punto, ¿qué puedes hacer?. Lo más fácil es cancelar el comando. Sin embargo, no
+puedes teclear simplemente \c en este ejemplo, dado que mysql ¡lo interpretará como parte del string
+que está leyendo! En vez de eso, introduce las comillas de cierre (para que mysql sepa que ya has
+terminado de introducir el string), y después teclea \c :
+
+mysql> SELECT * FROM mi_tabla WHERE nombre ="García AND edad < 30;
+ "> "\c
+mysql>
+
+El prompt vuelve a cambiar a mysql>, indicando que mysql está listo para un nuevo comando.
+
+Es importante saber qué significan los prompts '> y ">, dado que si introduces por error un string
+sin cerrar, cualquier otra línea que introduzcas serán ignoradas por mysql - ¡incluyendo una línea
+que contenga QUIT! Esto puede ser bastante confuso, especialmente si no sabes que debes introducir
+la comilla de cierre antes de poder cancelar el comando actual.
+
+8.3 Creando y usando una base de datos
+==========================================
+
+Ahora que sabes como introducir comandos, es hora de acceder a la base de datos.
+
+Supon que tienes varias mascotas en tu casa (tu pequeño "zoo") y que te gustaría llevar un control
+de varios tipos de información sobre estos animales. Puedes hacerlo creando tablas que guarden tus
+datos y cargandolas con la información deseada. Después puedes responder a diferentes series de
+preguntas sobre tus animales extrayendo los datos de las tablas. Esta sección explica cómo hacer
+todo esto:
+
+* Cómo crear una base de datos
+* Cómo crear una tabla
+* Cómo cargar los datos en la tabla
+* Cómo extraer información de la tabla de varias maneras
+* Cómo usar múltiples tablas
+
+La base de datos del zoo será simple (deliberadamente), pero no es difícil pensar en situaciones del
+mundo real en las que se pudiera utilizar una base de datos similar. Por ejemplo, se podría usar una base
+de datos como ésta en una granja para llevar un control del ganado, o por un veterinario para
+controlar el historial de sus pacientes.
+
+Usa la sentencia SHOW para averiguar qué bases de datos existen actualmente en el servidor:
+
+mysql> SHOW DATABASES;
++----------+
+| Database |
++----------+
+| mysql |
+| test |
++----------+
+
+Probablemente, la lista de las bases de datos será diferente en tu máquina, pero las bases de datos
+mysql y test es probable que se encuentren en esa lista. Se requiere la base de datos mysql pues
+describe los privilegios de acceso de los usuarios. La base de datos test se ofrece como campo de
+pruebas para que los usuarios prueben ahí sus teorías.
+
+Si la base de datos test existe, intenta acceder a ella:
+
+mysql> USE test
+Database changed
+
+Observa que USE, como QUIT, no requiere un punto y coma. (Puedes terminar este tipo de sentencias
+con un punto y coma si quieres, pero no es necesario.) La sentencia USE es especial en otro sentido,
+también: debe ser tecleada en una sola línea.
+
+Puedes usar la base de datos test (si tienes acceso a ella) para los ejemplos que siguen, pero
+cualquier cosa que crees en dicha base de datos puede ser eliminada por cualquiera que tenga acceso
+a ella. Por esta razón, deberías pedir a tu administrador MySQL permisos para usar una base de datos
+propia. Suponte que le quieres llamar zoo. El administrador necesitará ejecutar entonces la
+siguiente orden:
+
+mysql> GRANT ALL ON zoo.* TO tu_nombre;
+
+donde tu_nombre es el nombre de usuario MySQL que tengas asignado.
+
+ejemplo:
+
+mysql> GRANT ALL ON zoo.* TO chessy@localhost;
+Query OK, 0 rows affected (0.08 sec)
+
+
+8.3.1 Creando y seleccionando una base de datos
+==================================================
+
+Si el administrador creó la base de datos para tí cuando te configuró los permisos, puedes comenzar
+a usarla. En otro caso, deberás crearla tú mismo:
+
+[chessy@bishito chessy]$ mysql -u chessy
+Welcome to the MySQL monitor. Commands end with ; or \g.
+Your MySQL connection id is 6 to server version: 3.22.23b
+
+Type 'help' for help.
+
+mysql> CREATE DATABASE zoo;
+Query OK, 1 row affected (0.02 sec)
+
+
+Bajo Unix, los nombres de bases de datos son sensibles a las mayúsculas/minúsculas (a diferencia de
+los comandos SQL), así que deberás referirte siempre a tu base de datos con el nombre zoo, no como
+Zoo, ZOO o cualquier otra variante. Es es así también para las tablas. (Bajo Windows, esta
+restricción desaparece, aunque deberías referirte a las bases de datos y a las tablas usando la
+misma sintaxis en tus consultas.)
+
+Crear una base de datos no la selecciona para su uso, debes hacerlo explícitamente. Para hacer que
+la base de datos zoo sea tu base de datos de trabajo, usa el comando:
+
+mysql> USE zoo;
+Database changed
+
+Tu base de datos sólo necesita ser creada una vez, pero debes seleccionarla para usarla cada vez que
+comiences una sesión mysql. Puedes hacerlo lanzando un comando USE como se ha visto en el
+ejemplo. Alternativamente, puedes seleccionar la base de datos desde la línea de comandos cuando
+lanzas mysql. Simplemente especifica su nombre tras los parámetros de conexión que hayas
+escrito. Por ejemplo:
+
+shell> mysql -h host -u user -p zoo
+Enter password: ********
+
+Observa que en la línea de comandos del ejemplo, zoo no es tu password. Si quieres introducir tu
+password como parámetro en la línea de comandos tras la opción -p, debes hacerlo sin teclear un
+espacio en blanco intermedio (es decir, como -pmi_password, no como -p mi_password). Sin embargo, no
+es recomendable poner tu password en la línea de comandos, pues hacerlo lo expone a posibles
+miradas de otros usuarios conectados a tu máquina.
+
+8.3.2 Creando una tabla
+============================
+
+Crear una tabla es la parte fácil, pero hasta este momento está vacía, como te dice la orden SHOW
+TABLES:
+
+mysql> SHOW TABLES;
+Empty set (0.00 sec)
+
+La parte más dura consiste en decidir cual va a ser la estructura de tu base de datos: qué tablas
+necesitarás, y qué columnas tendrá cada una de ellas.
+
+Querrás seguramente una tabla que contenga un registro por cada una de tus mascotas. Esta tabla
+puede llamarse mascotas, y debería contener, como mínimo, el nombre de cada animal. Dado que el
+nombre por sí solo no es muy interesante, la tabla debería contener otra información. Por ejemplo,
+si más de una persona de tu familia tiene mascotas, probablemente quieras listar el propietario de
+cada animal. También querrás guardar información descriptiva básica como puede ser la especie y el
+sexo de cada mascota.
+
+¿Qué pasa con la edad? Podría ser de interés, pero no es una buena cosa a guardar en una base de
+datos. La edad cambia a medida que pasa el tiempo, lo que significa que tendrás que actualizar tus
+registros a menudo. En vez de eso, es mejor almacenar un valor fijo como la edad de
+nacimiento. Después, cada vez que necesites saber la edad, puedes calcularla como la diferencia
+entre la fecha actual y la fecha de nacimiento. MySQL ofrece funciones para realizar cálculos
+aritméticos entre fechas, por lo que esto no es difícil. Almacenar la fecha de nacimiento en lugar
+de la edad tiene también otras ventajas:
+
+* Puedes usar la base de datos para generar recordatorios de cumpleaños de mascotas. (Si crees que
+ este tipo de consulta es algo tonta, observa que es la misma pregunta que necesitarás hacer en el
+ contexto de una base de datos de un negocio para identificar clientes a los que pronto necesitarás
+ mandar un saludo por su cumpleaños, para ese toque personal asistido por ordenador :-)
+
+* Puedes calcular la edad en relación a fechas distintas a la fecha actual. Por ejemplo, si
+ almacenas la fecha de muerte en la base de datos, puedes calcular fácilmente lo vieja que era una
+ mascota cuando murió.
+
+Seguramente puedas pensar en otros tipos de información que sería útil en la tabla mascota, pero los
+identificados hasta ahora son suficientes por el momento: nombre, propietarios, especie, sexo, fecha
+de nacimiento y muerte.
+
+Usa una sentencia CREATE TABLE para especificar la estructura de tu tabla:
+
+mysql> CREATE TABLE mascota (nombre VARCHAR(20), propietario VARCHAR(20),
+ -> especie VARCHAR(20), sexo CHAR(1), nacimiento DATE, muerte DATE);
+
+VARCHAR es una buena elección para las columnas nombre, propietario y especie dado que los valores
+de estas columnas variarán su longitud. Las longitudes de estas columnas no necesitan ser iguales, y
+no necesitan ser 20. Puedes elegir cualquier longitud entre 1 y 255, cualquiera que te parezca
+razonable. (Si realizar una elección pobre y resulta que más adelante necesitas un campo mayor,
+MySQL ofrece una sentencia ALTER TABLE.)
+
+El sexo del animal puede ser representado en una variedad de formas, por ejemplo, "m" y "f", o
+quizás "masculino" y "femenino". Es más simple usar un único caracter, "m" ó "f".
+
+El uso del tipo de datos DATE para las columnas de nacimiento y muerte es una opción bastante
+obvia.
+
+Ahora que ya has creado una tabla, SHOW TABLES debería producir alguna salida:
+
+mysql> SHOW TABLES;
++---------------+
+| Tables in zoo |
++---------------+
+| mascota |
++---------------+
+
+Para verificar que tu tabla fue creada de la forma que esperabas, usa una sentencia DESCRIBE:
+
+mysql> DESCRIBE mascota;
++-------------+-------------+------+-----+---------+-------+
+| Field | Type | Null | Key | Default | Extra |
++-------------+-------------+------+-----+---------+-------+
+| nombre | varchar(20) | YES | | NULL | |
+| propietario | varchar(20) | YES | | NULL | |
+| especie | varchar(20) | YES | | NULL | |
+| sexo | char(1) | YES | | NULL | |
+| nacimiento | date | YES | | NULL | |
+| muerte | date | YES | | NULL | |
++-------------+-------------+------+-----+---------+-------+
+
+Puedes usar DESCRIBE en cualquier momento, por ejemplo, si olvidas los nombres de las columnas de tu
+tabla o a qué tipo de datos pertenecen.
+
+8.3.3 Cargando datos en una tabla
+=====================================
+
+Una vez creada tu tabla, necesitas poblarla. Las sentencias LOAD DATA e INSERT son útiles para esto.
+
+Suponte que tus registros de mascotas pueden ser descritos como se muestra más abajo. (Observa que
+MySQL espera que las fechas se introduzcan en formato AAAA-MM-DD; esto podría ser diferente a lo que
+estás acostumbrado.)
+
+nombre propietario especie sexo nacimiento muerte
+Fluffy Harold gato f 1993-02-04
+Claws Gwen gato m 1994-03-17
+Buffy Harold perro f 1989-05-13
+Fang Benny perro m 1990-08-27
+Bowser Diane perro m 1998-08-31 1995-07-29
+Chirpy Gwen pájaro f 1998-09-11
+Whistler Gwen pájaro 1997-12-09
+Slim Benny serpiente m 1996-04-29
+
+Dado que estás comenzando con una tabla vacía, una forma sencilla de poblarla consiste en crear un
+fichero de texto conteniendo una fila para cada uno de tus animales, y después cargar el contenido del
+fichero en la tabla con una sola sentencia.
+
+Puedes crear un fichero de texto "mascota.txt" conteniendo un registro por línea, con valores separados
+por tabuladores, y dados en el orden en el que las columnas fueron listadas en la sentencia CREATE
+TABLE. Para valores perdidos (como sexos desconocidos, o fechas de muerte de animales que aún están
+vivos), puedes usar valores NULL. Para representar estos en tu fichero de texto, use \N. Por
+ejemplo, el registro para Whistler el pájaro sería algo como esto (donde el espacio en blanco entre
+valores es un simple caracter de tabulación):
+
+Whistler Gwen pájaro \N 1997-12-09 \N
+
+Para cargar el fichero de texto "mascota.txt" en la tabla mascota, usa este comando:
+
+mysql> LOAD DATA LOCAL INFILE "mascota.txt" INTO TABLE mascota;
+
+Puedes especificar el valor de separación de columna y el marcador de final de línea explícitamente
+en la sentencia LOAD DATA si lo deseas, pero por defecto equivalen a TAB y LF (intro). Estos valores
+por defecto son suficientes para que la sentencia que lee el fichero "mascota.txt" funcione
+correctamente.
+
+Cuando quieras añadir nuevos registros uno a uno, la sentencia INSERT es muy útil. En su forma más
+simple, ofreces valores para cada columna, en el orden en el que las columnas fueron listadas en la
+sentencia CREATE TABLE. Supón que Diane consige un nuevo hamster llamado Puffball. Podrías añadir un
+nuevo registro usando una sentencia INSERT como esta:
+
+mysql> INSERT INTO mascota
+ -> VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);
+
+Observa que los valores string y fecha se espefican encerrados entre comillas. Observa también que,
+con INSERT, puedes insertar NULL directamente para representar un valor perdido. No usamos \N como
+hacíamos con LOAD DATA.
+
+De este ejemplo, deberías ser capaz de ver que hubiera dido mucho más costoso teclear todos los
+datos necesarios en la tabla mascota con sentencias INSERT que hacerlo como lo hemos hecho con una
+única sentencia LOAD DATA.
+
+
+8.3.4 Extrayendo información de una tabla
+===============================================
+
+
+La sentencia SELECT se usa para recabar información de una tabla. La forma
+general de la sentencia es:
+
+SELECT qué_seleccionar
+FROM de_qué_tabla
+WHERE condiciones_a_satisfacer
+
+qué_seleccionar indica qué es lo que quieres seleccionar. Puede ser una lista de
+columnas, o * para indicar "todas las columnas". de_qué_tabla indica la tabla de
+la que quieres extraer datos. La claúsula WHERE es opcional. Si está presente,
+condiciones_a_satisfacer especifica las codiciones que las filas deben cumplir
+para estar presentes en el resultado de la selección.
+
+8.3.4.1 Seleccionando todos los datos
+=======================================
+
+La forma más simplede SELECT recoge toda la información de una tabla:
+
+mysql> SELECT * FROM mascota;
++----------+-------------+-----------+------+------------+------------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++----------+-------------+-----------+------+------------+------------+
+| Bluffy | Harold | gato | f | 1993-02-04 | NULL |
+| Claws | Gwen | gato | m | 1994-03-17 | NULL |
+| Buffy | Harold | perro | f | 1989-05-13 | NULL |
+| Fang | Benny | perro | m | 1990-08-27 | NULL |
+| Bowser | Diane | perro | m | 1998-08-31 | 1995-07-29 |
+| Chirpy | Gwen | pájaro | f | 1998-09-11 | NULL |
+| Whistler | Gwen | pájaro | NULL | 1997-12-09 | NULL |
+| Slim | Benny | serpiente | m | 1996-04-29 | NULL |
+| Puffball | Diane | hamster | f | 1999-03-30 | NULL |
++----------+-------------+-----------+------+------------+------------+
+
+Esta forma de SELECT es útil si quieres revisar tu tabla al completo, por
+ejemplo, tras haberla cargado con tu conjunto inicial de datos. Como suele
+suceder, la salida ya muestra un error en tu fichero de datos: Bowser ¡parece
+haber nacido tras su muerte! Consultando tus papeles originales sobre el
+pedigree del perro, descubres que la fecha correcta de nacimiento es 1989, no
+1998.
+
+Existen al menos un par de maneras de arreglar esto:
+
+* Edita el fichero "mascota.txt" para corregir el error, después vacía la tabla
+ y vuelve a cargarla usando DELETE y LOAD DATA:
+
+mysql> DELETE from mascota;
+mysql> LOAD DATA LOCAL INFILE "mascota.txt" INTO TABLE mascota;
+
+Sin embargo, si haces esto, debes re-escribir el registro para Puffball.
+
+* Arreglar sólo el registro erróneo con la sentencia UPDATE:
+
+mysql> UPDATE mascota SET nacimiento="1989-08-31" WHERE nombre="Bowser";
+
+Como se muestra más arriba, es fácil recuperar el cuerpo de una data. Pero
+típicamente no querrás hacer eso, en particular cuando la tabla sea muy
+larga. Generalmente, estarás más interesado en responder a una pregunta en
+particular, en cuyo caso deberás especificar algunas restricciones en la
+información que deseas. Veamos algunas consultas de selección en términos de
+preguntas sobre tus mascotas que se deben responder.
+
+8.3.4.2 Seleccionando filas en particular
+=============================================
+
+Puedes seleccionar sólo filas en particular de tu tabla. Por ejemplo, si quieres
+verificar el cambio que has realizado a la fecha de nacimiento de Bowser,
+selecciona el registro de Bowser de la siguiente forma:
+
+mysql> SELECT * FROM mascota WHERE nombre="Bowser";
++--------+-------------+---------+------+------------+------------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++--------+-------------+---------+------+------------+------------+
+| Bowser | Diane | perro | m | 1989-08-31 | 1995-07-29 |
++--------+-------------+---------+------+------------+------------+
+
+La salida confirma que el año está correctamente registrado como 1989, no 1998.
+
+Las comparaciones de cadenas de texto son normalmente insensibles a las
+mayúsculas/minúsculas, por lo que puedes especificar el nombre como "bowser",
+"BOWSER", etc. El resultado de la consulta será el mismo.
+
+Puedes especificar condiciones en cualquier columna, no sólo el nombre. Por
+ejemplo, si quisieras saber qué animales nacieron a partir de 1998, examina la
+columna nacimiento:
+
+mysql> SELECT * FROM mascota WHERE nacimiento >= "1998-1-1";
++----------+-------------+---------+------+------------+--------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++----------+-------------+---------+------+------------+--------+
+| Chirpy | Gwen | pájaro | f | 1998-09-11 | NULL |
+| Puffball | Diane | hamster | f | 1999-03-30 | NULL |
++----------+-------------+---------+------+------------+--------+
+
+Puedes combinar condiciones, por ejemplo, para localizar los perros hembra:
+
+mysql> SELECT * FROM mascota WHERE especie="perro" AND sexo="f";
++--------+-------------+---------+------+------------+--------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++--------+-------------+---------+------+------------+--------+
+| Buffy | Harold | perro | f | 1989-05-13 | NULL |
++--------+-------------+---------+------+------------+--------+
+
+La consulta anterior usa el operador lógico AND. Existe también un operador OR:
+
+mysql> SELECT * FROM mascota WHERE especie="serpiente" OR especie="pájaro";
++----------+-------------+-----------+------+------------+--------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++----------+-------------+-----------+------+------------+--------+
+| Chirpy | Gwen | pájaro | f | 1998-09-11 | NULL |
+| Whistler | Gwen | pájaro | NULL | 1997-12-09 | NULL |
+| Slim | Benny | serpiente | m | 1996-04-29 | NULL |
++----------+-------------+-----------+------+------------+--------+
+
+AND y OR pueden entremezclarse. Si lo haces, es una buena idea el utilizar
+paréntesis para indicar cómo deberían agruparse las condiciones:
+
+mysql> SELECT * FROM mascota WHERE (especie="gato" AND sexo="m")
+ -> OR (especie="perro" AND sexo="f");
++--------+-------------+---------+------+------------+--------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++--------+-------------+---------+------+------------+--------+
+| Claws | Gwen | gato | m | 1994-03-17 | NULL |
+| Buffy | Harold | perro | f | 1989-05-13 | NULL |
++--------+-------------+---------+------+------------+--------+
+
+8.3.4.3 Seleccionando columnas en particular
+===================================================
+
+Si no quieres ver filas completas de tu tabla, simplemente nombra las columnas
+en las cuales estás interesado, separadas por comas. Por ejemplo, si quieres
+saber cuándo nacieron tus animales, selecciona las columnas nombre y nacimiento:
+
+mysql> SELECT nombre, nacimiento FROM mascota;
++----------+------------+
+| nombre | nacimiento |
++----------+------------+
+| Bluffy | 1993-02-04 |
+| Claws | 1994-03-17 |
+| Buffy | 1989-05-13 |
+| Fang | 1990-08-27 |
+| Bowser | 1989-08-31 |
+| Chirpy | 1998-09-11 |
+| Whistler | 1997-12-09 |
+| Slim | 1996-04-29 |
+| Puffball | 1999-03-30 |
++----------+------------+
+
+Para averiguar quién posee mascotas, usa esta consulta:
+
+mysql> SELECT propietario FROM mascota;
++-------------+
+| propietario |
++-------------+
+| Harold |
+| Gwen |
+| Harold |
+| Benny |
+| Diane |
+| Gwen |
+| Gwen |
+| Benny |
+| Diane |
++-------------+
+
+Sin embargo, observa que la consulta simplemente obtiene el campo propietario de
+cada registro, y algunos de ellos aparecen más de una vez. Para minimizar la
+salida, obtén cada registro de salida único una sola vez añadiendo la palabra
+reservada DISTINCT:
+
+mysql> SELECT DISTINCT propietario FROM mascota;
++-------------+
+| propietario |
++-------------+
+| Benny |
+| Diane |
+| Gwen |
+| Harold |
++-------------+
+
+Puedes usar una claúsula WHERE para combinar la selección de filas con la
+selección de columnas. Por ejemplo, para conseguir sólo las fechas de nacimiento
+de perros y gatos, usa esta consulta:
+
+mysql> SELECT nombre, especie, nacimiento FROM mascota
+ -> WHERE especie = "perro" OR especie = "gato";
++--------+---------+------------+
+| nombre | especie | nacimiento |
++--------+---------+------------+
+| Bluffy | gato | 1993-02-04 |
+| Claws | gato | 1994-03-17 |
+| Buffy | perro | 1989-05-13 |
+| Fang | perro | 1990-08-27 |
+| Bowser | perro | 1989-08-31 |
++--------+---------+------------+
+
+8.3.4.4 Ordenando filas
+===========================
+
+Tal vez hayas observado que en los ejemplos anteriores las filas del resultado
+se muestran sin ningún tipo de orden en particular. Sin embargo, a menudo es más
+fácil de examinar la salida de una consulta cuando las filas están ordenadas de
+alguna manera en particular. Para ordenar un resultado, usa la claúsula ORDER
+BY.
+
+Aquí mostramos las fechas de nacimiento de los animales, ordenadas por fecha:
+
+mysql> SELECT nombre, nacimiento FROM mascota ORDER BY nacimiento;
++----------+------------+
+| nombre | nacimiento |
++----------+------------+
+| Buffy | 1989-05-13 |
+| Bowser | 1989-08-31 |
+| Fang | 1990-08-27 |
+| Bluffy | 1993-02-04 |
+| Claws | 1994-03-17 |
+| Slim | 1996-04-29 |
+| Whistler | 1997-12-09 |
+| Chirpy | 1998-09-11 |
+| Puffball | 1999-03-30 |
++----------+------------+
+
+Para ordenar de forma inversa, añade la palabra reservada DESC (descendente) al
+nombre de la columna por la que estás ordenando:
+
+mysql> SELECT nombre, nacimiento FROM mascota ORDER BY nacimiento DESC;
++----------+------------+
+| nombre | nacimiento |
++----------+------------+
+| Puffball | 1999-03-30 |
+| Chirpy | 1998-09-11 |
+| Whistler | 1997-12-09 |
+| Slim | 1996-04-29 |
+| Claws | 1994-03-17 |
+| Bluffy | 1993-02-04 |
+| Fang | 1990-08-27 |
+| Bowser | 1989-08-31 |
+| Buffy | 1989-05-13 |
++----------+------------+
+
+Puedes ordenar por múltiples columnas. Por ejemplo, para ordenar por tipo de
+animal, después por fecha de nacimiento dentro del mismo tipo de animal estando
+los animales más jóvenes primero, usa la siguiente consulta:
+
+mysql> SELECT nombre, especie, nacimiento FROM mascota ORDER BY especie, nacimiento DESC;
++----------+-----------+------------+
+| nombre | especie | nacimiento |
++----------+-----------+------------+
+| Claws | gato | 1994-03-17 |
+| Bluffy | gato | 1993-02-04 |
+| Puffball | hamster | 1999-03-30 |
+| Chirpy | pájaro | 1998-09-11 |
+| Whistler | pájaro | 1997-12-09 |
+| Fang | perro | 1990-08-27 |
+| Bowser | perro | 1989-08-31 |
+| Buffy | perro | 1989-05-13 |
+| Slim | serpiente | 1996-04-29 |
++----------+-----------+------------+
+
+Observa que la palabra reservada DESC se aplica sólo al nombre de columna que
+preceda a la palabra reservada (nacimiento); los valores especie siguen siendo
+ordenados en forma ascendente.
+
+8.3.4.5 Cálculos de fecha
+============================
+
+MySQL ofrece muchas funciones que puedes usar para realizar cálculos con fechas,
+por ejemplo, para calcular edades o extraer partes de fechas.
+
+Para determinar cuantos años tiene cada una de tus mascotas, puedes calcular la
+edad como la diferencia entre la fecha de nacimiento y la fecha actual. Puedes
+hacerlo convirtiendo las dos fechas a dias, coge la diferencia, y divídela por
+365 (el número de dias en un año):
+
+mysql> select nombre, (TO_DAYS(NOW())-TO_DAYS(nacimiento))/365 FROM mascota;
++----------+------------------------------------------+
+| nombre | (TO_DAYS(NOW())-TO_DAYS(nacimiento))/365 |
++----------+------------------------------------------+
+| Bluffy | 6.94 |
+| Claws | 5.83 |
+| Buffy | 10.68 |
+| Fang | 9.39 |
+| Bowser | 10.38 |
+| Chirpy | 1.34 |
+| Whistler | 2.10 |
+| Slim | 3.71 |
+| Puffball | 0.79 |
++----------+------------------------------------------+
+
+Aunque la consulta funcione, existen algunos puntos que podrían ser
+mejorados. Primero, el resultado podría ser revisado más fácilmente si las filas
+se presentaran ordenadas de alguna manera. Segundo, la cabecera de la columna
+edad no es muy significativa.
+
+El primer problema puede ser solucionado añadiendo una cláusula ORDER BY nombre
+para ordenar la salida por nombre. Para arreglar el tema del encabezamiento de
+columna, puedes darle un nombre a dicha columna de tal forma que aparezca una
+etiqueta diferente en la salida (esto es lo que se llama un alias de columna):
+
+mysql> select nombre, (TO_DAYS(NOW())-TO_DAYS(nacimiento))/365 AS edad
+ -> FROM mascota ORDER BY nombre;
++----------+-------+
+| nombre | edad |
++----------+-------+
+| Bluffy | 6.94 |
+| Bowser | 10.38 |
+| Buffy | 10.68 |
+| Chirpy | 1.34 |
+| Claws | 5.83 |
+| Fang | 9.39 |
+| Puffball | 0.79 |
+| Slim | 3.71 |
+| Whistler | 2.10 |
++----------+-------+
+
+Para ordenar la salida por edad en lugar de por nombre, puedes hacerlo usando
+símplemente una cláusula ORDER BY diferente:
+
+mysql> select nombre, (TO_DAYS(NOW())-TO_DAYS(nacimiento))/365 AS edad
+ -> FROM mascota ORDER BY edad;
++----------+-------+
+| nombre | edad |
++----------+-------+
+| Puffball | 0.79 |
+| Chirpy | 1.34 |
+| Whistler | 2.10 |
+| Slim | 3.71 |
+| Claws | 5.83 |
+| Bluffy | 6.94 |
+| Fang | 9.39 |
+| Bowser | 10.38 |
+| Buffy | 10.68 |
++----------+-------+
+
+Puede usarse una consulta similar para determinar la edad de la muerte para los
+animales que hayan muerto. Puedes determinar qué animales son estos comprobando
+si el valor muerte es NULL o no. Después, para aquellos que no tengan un valor
+NULL, calcular la diferencia entre los valores muerte y nacimiento:
+
+mysql> select nombre, nacimiento, muerte,
+ -> (TO_DAYS(NOW())-TO_DAYS(nacimiento))/365 AS edad
+ -> FROM mascota WHERE muerte IS NOT NULL ORDER BY edad;
++--------+------------+------------+-------+
+| nombre | nacimiento | muerte | edad |
++--------+------------+------------+-------+
+| Bowser | 1989-08-31 | 1995-07-29 | 10.38 |
++--------+------------+------------+-------+
+
+La consulta usa muerte IS NOT NULL en lugar de muerte != NULL dado que NULL es
+un valor especial. Esto se explica más adelante. [Puedes consultar la sección
+[Working with NULL] del manual de MySQL.
+
+¿Qué harías si quisieras saber qué animales cumplen años el mes que viene? Para
+este tipo de cálculos, año y día son irrelevantes, simplemente querrás extraer
+la parte mes de la columna nacimiento. MySQL ofrece muchas funciones de
+extracción de parte-de-fecha, como YEAR(),MONTH() y DAY(). La función apropiada
+para nuestro problema es MONTH(). Para ver cómo funciona, ejecuta una consulta
+rápida que muestre el valor de la fecha de nacimiento y el mes de nacimiento
+(MONTH(nacimiento)):
+
+mysql> SELECT nombre, nacimiento, MONTH(nacimiento) FROM mascota;
++----------+------------+-------------------+
+| nombre | nacimiento | MONTH(nacimiento) |
++----------+------------+-------------------+
+| Bluffy | 1993-02-04 | 2 |
+| Claws | 1994-03-17 | 3 |
+| Buffy | 1989-05-13 | 5 |
+| Fang | 1990-08-27 | 8 |
+| Bowser | 1989-08-31 | 8 |
+| Chirpy | 1998-09-11 | 9 |
+| Whistler | 1997-12-09 | 12 |
+| Slim | 1996-04-29 | 4 |
+| Puffball | 1999-03-30 | 3 |
++----------+------------+-------------------+
+
+Buscar animales que hayan nacido en el mes próximo es también sencillo de
+realizar. Suponte que Abril es el mes actual. Entonces el valor del mes es 4 y
+lo que buscas son animales nacidos en Mayo (mes 5):
+
+mysql> SELECT nombre, nacimiento FROM mascota WHERE MONTH(nacimiento) = 5;
++--------+------------+
+| nombre | nacimiento |
++--------+------------+
+| Buffy | 1989-05-13 |
++--------+------------+
+
+Existe una pequeña complicación si el mes actual es Diciembre, por supuesto. No
+puedes añadir simplemente uno al número de mes (12) y buscar animales nacidos en
+el mes 13, dado que no existe tal mes. En lugar de eso, debes buscar animales
+nacidos en Enero (mes 1).
+
+Puedes escribir la consulta de tal forma que funcione independientemente del mes
+en el que estemos. De esa forma no tendrás que usar un número de mes en
+particular en la consulta. DATE_ADD() te permite añadir un intervalo de tiempo a
+una fecha dada. Si añades un mes al valor de NOW(), y después extraes la parte
+del mes con MONTH(), el resultado produce el mes del cumpleaños que buscamos:
+
+
+mysql> select NOW();
++---------------------+
+| NOW() |
++---------------------+
+| 2000-01-13 18:13:09 |
++---------------------+
+
+mysql> SELECT nombre, nacimiento FROM mascota
+ -> WHERE MONTH(nacimiento) = MONTH(DATE_ADD(NOW(),INTERVAL 1 MONTH));
++--------+------------+
+| nombre | nacimiento |
++--------+------------+
+| Bluffy | 1993-02-04 |
++--------+------------+
+
+Una manera difente de conseguir los mismos resultados es añadir 1 al mes actual
+para conseguir el mes siguiente (tras usar la función módulo (MOD) para
+convertir el valor de mes actual en 0 si estamos en Diciembre (mes 12)):
+
+mysql> SELECT nombre, nacimiento FROM mascota
+ -> WHERE MONTH(nacimiento) = MOD(MONTH(NOW()),12) +1;
++--------+------------+
+| nombre | nacimiento |
++--------+------------+
+| Bluffy | 1993-02-04 |
++--------+------------+
+
+
+8.3.4.6 Trabajando con valores NULL
+=======================================
+
+Los valores NULL pueden ser sorprenderte hasta que te acostumbras a
+usarlos. Conceptualmente, NULL significa "valor perdido" o "valor desconocido" y
+se trata de forma diferente que otros valores. Para realizar comparaciones
+respecto a NULL, no puedes utilizar los operadores de comparación aritméticos
+como =, < o != . Puedes realizar una demostración de esto, prueba la siguiente consulta:
+
+mysql> SELECT 1 = NULL, 1 != NULL, 1 < NULL, 1 > NULL;
++----------+-----------+----------+----------+
+| 1 = NULL | 1 != NULL | 1 < NULL | 1 > NULL |
++----------+-----------+----------+----------+
+| NULL | NULL | NULL | NULL |
++----------+-----------+----------+----------+
+
+Ciertamente, de estas comparaciones no se pueden extraer resultados
+significativos. Para conseguirlo, usa los operadores IS NULL y IS NOT NULL:
+
+mysql> SELECT 1 IS NULL, 1 IS NOT NULL;
++-----------+---------------+
+| 1 IS NULL | 1 IS NOT NULL |
++-----------+---------------+
+| 0 | 1 |
++-----------+---------------+
+
+En MySQL, 0 significa falso y 1 significa VERDADERO.
+
+Este tratamiento especial de NULL fue la causa de que en la sección anterior
+fuera necesario determinar qué animales ya no vivían usando "muerte IS NOT NULL"
+en lugar de "muerte != NULL".
+
+8.3.4.7 Asociación/Coincidencia de patrones (PATTERN MATCHING)
+================================================================
+
+MySQL ofrece las características de asociación de patrones estándar así como
+una forma de coincidencia de patrones basadas en expresiones regulares
+extendidas similares a las usadas por utilidades UNIX como vi, grep y sed.
+
+La asociación de patrones SQL te permite usar '_' para asociar cualquier
+caracter simple, y '%' para asociar un número arbitrario de caracteres
+(incluyendo cero caracteres). Los patrones SQL no toman en cuenta las
+diferencias entre mayúsculas y minúsculas. Se muestran debajo algunos
+ejemplos. Observa que no se utiliza = o != en el trabajo con patrones SQL;
+utiliza en su lugar los operadores de comparación LIKE o NOT LIKE.
+
+Para buscar nombres que comienzan por "b":
+
+mysql> SELECT * FROM mascota WHERE nombre LIKE "b%";
++--------+-------------+---------+------+------------+------------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++--------+-------------+---------+------+------------+------------+
+| Bluffy | Harold | gato | f | 1993-02-04 | NULL |
+| Buffy | Harold | perro | f | 1989-05-13 | NULL |
+| Bowser | Diane | perro | m | 1989-08-31 | 1995-07-29 |
++--------+-------------+---------+------+------------+------------+
+
+Para buscar nombres que terminen por "fy":
+
+mysql> SELECT * FROM mascota WHERE nombre LIKE "%fy";
++--------+-------------+---------+------+------------+--------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++--------+-------------+---------+------+------------+--------+
+| Bluffy | Harold | gato | f | 1993-02-04 | NULL |
+| Buffy | Harold | perro | f | 1989-05-13 | NULL |
++--------+-------------+---------+------+------------+--------+
+
+Para buscar nombres que contengan una "w":
+
+mysql> SELECT * FROM mascota WHERE nombre LIKE "%w%";
++----------+-------------+---------+------+------------+------------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++----------+-------------+---------+------+------------+------------+
+| Claws | Gwen | gato | m | 1994-03-17 | NULL |
+| Bowser | Diane | perro | m | 1989-08-31 | 1995-07-29 |
+| Whistler | Gwen | pájaro | NULL | 1997-12-09 | NULL |
++----------+-------------+---------+------+------------+------------+
+
+Para buscar nombres de longitud cinco caracteres, usa el patrón "_" :
+
+mysql> SELECT * FROM mascota WHERE nombre LIKE "_____";
++--------+-------------+---------+------+------------+--------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++--------+-------------+---------+------+------------+--------+
+| Claws | Gwen | gato | m | 1994-03-17 | NULL |
+| Buffy | Harold | perro | f | 1989-05-13 | NULL |
++--------+-------------+---------+------+------------+--------+
+
+El otro tipo de asociación de patrones ofrecido por MySQL utiliza expresiones
+regulares extendidas. Cuando se realiza una comprobación buscando una coincidencia
+para este tipo de patrón, se deben usar los operadores REGEXP y NOT REGEXP (o
+RLIKE y NOT RLIKE, dado que son sinónimos).
+
+Algunas características de las expresiones regulares extendidas son:
+
+* `.' se asocia con cualquier caracter (pero sólo uno)
+
+* Una clase de caracteres `[...]' se asocia con culquier caracter contenido
+ dentro de los corchetes. Por ejemplo, `[abc]' se asocia con 'a', 'b' ó
+
+* 'c'. Para nombrar un rango de caracteres, usa un guión. `[a-z]' se asocia con
+cualquier letra en minúscula, donde '[0-9]' se asocia con cualquier dígito.
+
+* '*' se asocia con 0 o más instancias de lo que preceda al asterisco. Por
+ ejemplo,'a*' coincide con cualquier número de a's,'[0-9]*' se asocia con
+ cualquier número de dígitos, y '.*' se asocia con cualquier cosa.
+
+* Las expresiones regulares son sensibles a las mayúsculas/minúsculas, pero
+ puedes utilizar una clase caracter para asociar ambos casos si los deseas. Por
+ ejemplo, '[aA]' coincide tanto con la letra a minúscula como con la letra A
+ mayúscula y '[a-zA-Z]' coincide con cualquier letra en cualquier modo
+ mayúscula/minúscula.
+
+* El patrón se asocia si ocurre en cualquier lugar dentro del valor a ser
+ probado (los patrones SQL coinciden sólo si se asocian con el valor
+ completo).
+
+* Para anclar un patrón de manera que se busque la coincidencia bien al comienzo
+ o bien al final del valor a ser comprobado, usa '^' al comienzo del patrón o
+ '$' al final del patrón, respectivamente.
+
+Para demostrar cómo funcionan las expresiones regulares, las consultas LIKE
+mostradas antes son reescritas debajo para usar REGEXP:
+
+Para buscar nombres que comiencen por "b", usa '^' para buscar la coincidencia
+al comienzo del nombre y '[bB]' para buscar la asociación tanto con la b
+minúscula como con la b mayúscula:
+
+mysql> SELECT * FROM mascota WHERE nombre REGEXP "^[bB]";
++--------+-------------+---------+------+------------+------------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++--------+-------------+---------+------+------------+------------+
+| Bluffy | Harold | gato | f | 1993-02-04 | NULL |
+| Buffy | Harold | perro | f | 1989-05-13 | NULL |
+| Bowser | Diane | perro | m | 1989-08-31 | 1995-07-29 |
++--------+-------------+---------+------+------------+------------+
+
+Para buscar nombres que terminen por "fy", usa "$" para buscar la coincidencia
+al final del nombre:
+
+mysql> SELECT * FROM mascota WHERE nombre REGEXP "fy$";
++--------+-------------+---------+------+------------+--------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++--------+-------------+---------+------+------------+--------+
+| Bluffy | Harold | gato | f | 1993-02-04 | NULL |
+| Buffy | Harold | perro | f | 1989-05-13 | NULL |
++--------+-------------+---------+------+------------+--------+
+
+Para buscar nombres que contengan una "w", utiliza "[wW]" para buscar la
+asociación tanto en mayúsculas como minúsculas:
+
+ mysql> SELECT * FROM mascota WHERE nombre REGEXP "[wW]";
++----------+-------------+---------+------+------------+------------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++----------+-------------+---------+------+------------+------------+
+| Claws | Gwen | gato | m | 1994-03-17 | NULL |
+| Bowser | Diane | perro | m | 1989-08-31 | 1995-07-29 |
+| Whistler | Gwen | pájaro | NULL | 1997-12-09 | NULL |
++----------+-------------+---------+------+------------+------------+
+
+Dado que un patrón de una expresión regular se asocia si ocurre en cualquier
+lugar del valor, no es necesario poner un caracter comodín en ningún lado del
+patrón para conseguir que se asocie con el valor completo como harías si usaras
+un patrón SQL.
+
+Para buscar nombres conteniendo exactamente cinco caracteres, usa "^" y "$" para
+asociar el comienzo y el final de un nombre, y cinco instancias de "." entre
+ellos:
+
+mysql> SELECT * FROM mascota WHERE nombre REGEXP "^.....$";
++--------+-------------+---------+------+------------+--------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++--------+-------------+---------+------+------------+--------+
+| Claws | Gwen | gato | m | 1994-03-17 | NULL |
+| Buffy | Harold | perro | f | 1989-05-13 | NULL |
++--------+-------------+---------+------+------------+--------+
+
+También podrías haber escrito la consulta anterior usando el operador '{n}'
+"repetir n veces":
+
+mysql> SELECT * FROM mascota WHERE nombre REGEXP "^.{5}$";
++--------+-------------+---------+------+------------+--------+
+| nombre | propietario | especie | sexo | nacimiento | muerte |
++--------+-------------+---------+------+------------+--------+
+| Claws | Gwen | gato | m | 1994-03-17 | NULL |
+| Buffy | Harold | perro | f | 1989-05-13 | NULL |
++--------+-------------+---------+------+------------+--------+
+
+
+8.3.4.8 Contando filas
+=======================
+
+Las bases de datos son usadas a menudo para responder a la pregunta, "¿cuantas
+veces aparece un determinado tipo de datos en una tabla?". Por ejemplo, podrías
+querer saber cuántas mascotas tienes, o cuántas mascotas tiene cada propietario,
+o podrías querer realizar varios tipos de censos respecto a tus animales.
+
+Contar el número total de animales que tienes es lo mismo que preguntar
+"¿cuántas filas hay en la tabla mascota?", dado que hay sólo una fila por
+mascota. La función COUNT() cuenta el número de resultados no-NULL , así pues,
+la consulta a realizar para contar el número de animales tiene la siguiente forma:
+
+mysql> SELECT COUNT(*) FROM mascota;
++----------+
+| COUNT(*) |
++----------+
+| 9 |
++----------+
+
+Antes, conseguiste los nombres de las personas que poseen una mascota. Puedes
+usar COUNT() para averiguar cuántas mascotas tiene cada propietario:
+
+mysql> SELECT propietario, COUNT(*) FROM mascota GROUP BY propietario;
++-------------+----------+
+| propietario | COUNT(*) |
++-------------+----------+
+| Benny | 2 |
+| Diane | 2 |
+| Gwen | 3 |
+| Harold | 2 |
++-------------+----------+
+
+Observa el uso de GROUP BY para agrupar todos los registros de cada
+propietario. Si no lo hubiéramos puesto, todo lo que conseguirias sería un
+mensaje de error:
+
+mysql> SELECT propietario, COUNT(propietario) FROM mascota;
+ERROR 1140: Mixing of GROUP columns (MIN(),MAX(),COUNT()...) with no GROUP
+columns is illegal if there is no GROUP BY clause
+
+COUNT() y GROUP BY son útiles para la caracterización de tus datos de varias
+formas. Los siguientes ejemplos muestran difentes maneras para realizar
+operaciones de censo animal.
+
+Número de animales por especies:
+
+mysql> SELECT especie, COUNT(*) FROM mascota GROUP BY especie;
++-----------+----------+
+| especie | COUNT(*) |
++-----------+----------+
+| gato | 2 |
+| hamster | 1 |
+| pájaro | 2 |
+| perro | 3 |
+| serpiente | 1 |
++-----------+----------+
+
+Número de animales por sexo:
+
+mysql> SELECT sexo , COUNT(*) FROM mascota GROUP BY sexo;
++------+----------+
+| sexo | COUNT(*) |
++------+----------+
+| NULL | 1 |
+| f | 4 |
+| m | 4 |
++------+----------+
+
+(En este resultado, NULL indica "sexo desconocido")
+
+El número de animales por combinación de especies y sexo:
+
+mysql> SELECT especie , sexo, COUNT(*) FROM mascota GROUP BY especie, sexo;
++-----------+------+----------+
+| especie | sexo | COUNT(*) |
++-----------+------+----------+
+| gato | f | 1 |
+| gato | m | 1 |
+| hamster | f | 1 |
+| pájaro | NULL | 1 |
+| pájaro | f | 1 |
+| perro | f | 1 |
+| perro | m | 2 |
+| serpiente | m | 1 |
++-----------+------+----------+
+
+No necesitas recuperar una tabla completa cuando uses COUNT(). Por ejemplo, la
+consulta anterior, cuando se realiza sólo sobre perros y gatos, se escribe así:
+
+mysql> SELECT especie , sexo, COUNT(*) FROM mascota
+ -> WHERE especie = "perro" OR especie = "gato"
+ -> GROUP BY especie, sexo;
++---------+------+----------+
+| especie | sexo | COUNT(*) |
++---------+------+----------+
+| gato | f | 1 |
+| gato | m | 1 |
+| perro | f | 1 |
+| perro | m | 2 |
++---------+------+----------+
+
+O, si quieres conocer el número de animales por sexo sólo para animales de sexo
+conocido:
+
+mysql> SELECT especie , sexo, COUNT(*) FROM mascota
+ -> WHERE sexo IS NOT NULL
+ -> GROUP BY especie, sexo;
++-----------+------+----------+
+| especie | sexo | COUNT(*) |
++-----------+------+----------+
+| gato | f | 1 |
+| gato | m | 1 |
+| hamster | f | 1 |
+| pájaro | f | 1 |
+| perro | f | 1 |
+| perro | m | 2 |
+| serpiente | m | 1 |
++-----------+------+----------+
+
+
+8.3.5 Usando más de una tabla
+===============================
+
+La tabla mascota guarda datos sobre las mascotas que posees. Si quieres guardar
+otra información sobre ellos, como eventos en sus vidas, visitas al veterinario
+o cuándo han tenido hermanos, necesitas otra tabla. ¿Cómo debería ser esta otra
+tabla?
+
+* Deberá contener el nombre de la mascota de tal forma que pudieras saber a qué
+ animal corresponde cada evento almacenado en la misma.
+
+* Necesitará una fecha para conocer cuándo ocurrió el evento.
+
+* Necesitará un campo para describir el evento
+
+* Si quieres ser capaz de categorizar los eventos, sería útil tener un campo de
+ tipo evento.
+
+Dadas estas consideraciones, la sentencia CREATE TABLE para la tabla "evento" se
+parecería a esto:
+
+mysql> CREATE TABLE evento (nombre VARCHAR(20), fecha DATE,
+ -> tipo VARCHAR(15), anotación VARCHAR(255));
+
+Como ocurría con la tabla mascota, es más fácil cargar los registros iniciales
+creando un fichero de texto delimitado por tabuladores conteniendo la
+información:
+
+Fluffy 1995-05-15 parto 4 cachorros, 3 hembras, 1 macho
+Buffy 1993-06-23 parto 5 cachorros, 2 hembras, 3 machos
+Buffy 1994-06-19 parto 3 cachorros, 3 hembras
+Chirpy 1999-03-21 veterinario necesitó enderezamiento de pico
+Slim 1997-08-03 veterinario costilla rota
+Bowser 1991-10-12 perrera
+Fang 1991-10-12 perrera
+Fang 1998-08-28 cumpleaños Se le regala un nuevo juguete de goma
+Claws 1998-03-17 cumpleaños Se le regala un nuevo collar de pulgas
+Whistler 1998-12-09 cumpleaños Primer cumpleaños
+
+
+Carga los registros así:
+
+mysql> LOAD DATA LOCAL INFILE "evento.txt" INTO TABLE evento;
+
+Basándote en lo que has aprendido de las consultas que has ejecutado em la tabla
+mascota, deberías ser capaz de realizar recuperaciones de datos en los registros
+de la tabla "evento"; los principios son los mismos. ¿Pero qué hacer cuando la
+tabla evento no sea suficiente por sí sola de responder a cuestiones que
+podrías llegar a realizar?
+
+Supón que quisieras averiguar las edades de cada mascota al tener cachorros. La
+tabla evento indica cuándo ha ocurrido esto, pero para calcular la edad de la
+madre, necesitas su fecha de nacimiento. Dado que eso está almacenado en la
+tabla mascota, necesitas ambas tablas para la consulta:
+
+mysql> SELECT mascota.nombre , (TO_DAYS(fecha) - TO_DAYS(nacimiento))/365 AS edad, anotación
+ -> FROM mascota, evento
+ -> WHERE mascota.nombre = evento.nombre AND tipo = "parto";
++--------+------+----------------------------------+
+| nombre | edad | anotación |
++--------+------+----------------------------------+
+| Fluffy | 2.27 | 4 cachorros, 3 hembras, 1 macho |
+| Buffy | 4.12 | 5 cachorros, 2 hembras, 3 machos |
+| Buffy | 5.10 | 3 cachorros, 3 hembras |
++--------+------+----------------------------------+
+
+Existen varios puntos que anotar sobre esta consulta:
+
+* La cláusula FROM lista dos tablas dado que la consulta necesita extraer
+ información de las dos.
+
+* Cuando se combina la información de múltiples tablas, necesitas especificar
+ cómo pueden ser asociados los registros de una tabla con los registros de la
+ otra. Esto es fácil dado que ambas tienen una columna nombre (N.T.: nombre es
+ una clave extranjera). La consulta usa la cláusula WHERE para combinar los
+ registros de las dos tablas basándose en los valores de nombre.
+
+* Dado que la columna nombre aparece en ambas tablas, debes ser específico sobre
+ a qué tabla te refieres cuando estés hablando de esa columna. Esto se realiza
+ poniendo el nombre de la tabla como prefijo de la columna.
+
+No necesitas tener dos tablas diferentes para realizar un join. En algunas
+ocasiones es útil realizar un join de una tabla consigo misma, si quieres comparar
+registros de una tabla con otros registros en la misma tabla. Por ejemplo, para buscar
+parejas de sexos entre tus mascotas, puedes enlazar la tabla mascota consigo
+mismo para emaparejar machos y hembras de las mismas especies:
+
+mysql> SELECT p1.nombre, p1.sexo, p2.nombre, p2.sexo, p1.especie
+ -> FROM mascota AS p1, mascota AS p2
+ -> WHERE p1.especie = p2.especie AND p1.sexo = "f" AND p2.sexo = "m";
++--------+------+--------+------+---------+
+| nombre | sexo | nombre | sexo | especie |
++--------+------+--------+------+---------+
+| Fluffy | f | Claws | m | gato |
+| Buffy | f | Fang | m | perro |
+| Buffy | f | Bowser | m | perro |
++--------+------+--------+------+---------+
+
+
+En esta consulta, especificamos un par de alias para el nombre de las tablas
+y ser capaces así de referirnos a las columnas y saber en todo momento a qué
+instancia de qué tabla se asocia cada referencia de columna.
+
+8.4 Obtener información sobre bases de datos y tablas
+================================================================
+
+¿Qué ocurre si olvidas el nombre de una base de datos o de una tabla, o cuál es
+la estructura de una tabla dada (ejm. : ¿cómo se llaman sus columnas?) MySQL
+soluciona este problema a través de numerosas sentencias que ofrecen información
+sobre las bases de datos y las tablas que soporta.
+
+Ya hemos visto SHOW DATABASES, que lista las bases de datos gestionadas por el
+servidor. Para averiguar qué base de datos está actualmente seleccionada, usa la
+función DATABASE():
+
+mysql> SELECT DATABASE();
++------------+
+| DATABASE() |
++------------+
+| zoo |
++------------+
+
+Si aún no has seleccionado ninguna base de datos, el resultado estará en blanco.
+
+Para averiguar qué tablas contiene la base de datos actual (por ejemplo, cuando
+no estás seguro sobre el nombre de una tabla), usa este comando:
+
+mysql> SHOW TABLES;
++---------------+
+| Tables in zoo |
++---------------+
+| evento |
+| mascota |
++---------------+
+
+Si quieres averiguar la estructura de una tabla, el comando DESCRIBE te será
+útil; muestra información sobre cada columna de una tabla:
+
+mysql> DESCRIBE mascota;
++-------------+-------------+------+-----+---------+-------+
+| Field | Type | Null | Key | Default | Extra |
++-------------+-------------+------+-----+---------+-------+
+| nombre | varchar(20) | YES | | NULL | |
+| propietario | varchar(20) | YES | | NULL | |
+| especie | varchar(20) | YES | | NULL | |
+| sexo | char(1) | YES | | NULL | |
+| nacimiento | date | YES | | NULL | |
+| muerte | date | YES | | NULL | |
++-------------+-------------+------+-----+---------+-------+
+
+Field indica el nombre de la columna, Type es el tipo de datos para la columna,
+Null indica si la columna puede contener o no valores NULL, Key indica si la
+columna está indexada o no, y Default especifica el valor por defecto para la
+columna.
+
+Si tienes índices en una tabla, SHOW INDEX FROM nombre_tabla te mostrará
+información sobre ellos.
+
+8.5 Usando mysql en modo batch
+=================================
+
+En las secciones previas, hemos usado mysql interactivamente para introducir
+consultas y observar los resultados. También puedes ejecutar mysql en modo
+batch. Para realizarlo, escribe los comandos que quieras ejecutar en un fichero,
+después pídele a mysql que lea su entrada desde el fichero:
+
+shell> mysql < fichero-batch
+
+(N.T.: en ocasiones se traduce como fichero por lotes)
+
+Si necesitas especificar parámetros de conexión en la línea de comandos, el
+comando podría parecerse a esto:
+
+shell> mysql -h host -u user -p < fichero-batch
+Enter password: ********
+
+Cuando usas MySQL de esta manera, estás creando un fichero script (de guión), y
+después ejecutando el script.
+
+¿Por qué usar un script? He aquí algunas razones:
+
+* Si ejecutas una consulta repetidamente (digamos, cada día o cada semana), el
+ construir un script con esta consulta te permite evitar volver a teclearla
+ cada vez que la ejecutes.
+
+* Puedes generar nuevas consultas a partir de consultas ya existentes similares
+ simplemente copiando y editando los ficheros script.
+
+* El modo batch puede ser también muy útil cuando estés desarrollando una
+ consulta, particularmente para comandos multi-línea o múltiples secuencias de
+ comandos de múltiples sentencias. Si cometes un error, no necesitas reescribir
+ todo. Símplemente edita el script para corregir el error, y después pídele a
+ mysql que lo vuelva a ejecutar.
+
+* Si tienes una consulta que produce resultados muy largos, puedes usar un
+ paginador para filtrar esta salida en lugar de ver cómo se desplaza fuera del
+ alcance de tu pantalla:
+
+
+shell> mysql < fichero_batch | more
+
+* Puedes redirigir la salida a un fichero para un procesamiento posterior:
+
+shell> mysql < fichero_batch > mysql.out
+
+* Puedes distribuir tu script a otras personas para que puedan ejecutar también
+ tus comandos.
+
+* Algunas situaciones no permiten un uso interactivo, por ejemplo, cuando
+ ejecutas una consulta como una tarea de cron. (N.T.: cron es un comando UNIX
+ que sirve para planificar y ejecutar comandos UNIX en el tiempo). En este
+ caso, debes usar el procesamiento por lotes.
+
+El formato de salida por defecto es diferente (más conciso) cuando ejecutas
+mysql en modo batch que cuando lo usas de manera interactiva. Por ejemplo, la
+salida de SELECT DISTINCT especie FROM mascota es la siguiente cuando se
+ejecuta de manera interactiva:
+
+mysql> SELECT DISTINCT especie FROM mascota;
++-----------+
+| especie |
++-----------+
+| gato |
+| hamster |
+| pájaro |
+| perro |
+| serpiente |
++-----------+
+
+Y la siguiente si se ejecuta en modo batch:
+
+especie
+gato
+hamster
+pájaro
+perro
+serpiente
+
+Si quieres obtener el formato de salida del modo interactivo también en modo
+batch, usa mysql -t. Para redirigir a salida estándar los comandos que se están
+ejecutando, usa mysql -vvv.
+
+
+
+8.6 Consultas del proyecto gemelos
+
+En Analytikerna y Lentus, hemos estado realizando el trabajo de campo y sistemas para
+un gran proyecto de investigación. Este proyecto es una colaboración entre el Instituto de
+Medicina Medioambiental en el Karolinska Institutet Stockholm y la Sección en Investigación
+Clínica en Envejecimiento y Psicología en la Universidad del Sur de California.
+
+El proyecto consistió en una parte de selección donde todos los gemelos en Suecia mayores de
+65 años eran entrevistados por teléfono. Los gemelos que reunían ciertos criterios pasaban a la
+siguiente fase. En esta fase posterior, los gemelos que querían participar eran visitados por
+un equipo doctor/enfermera. Algunos de los exámenes incluían exámenes físicos y neuropsicológicos,
+pruebas de laboratorio, neuroimágenes, valoración del estado psicológico, y recopilación de la
+historia familiar. Además, se recogieron datos sobre los factores de riesgo médicos y
+medioambientales.
+
+Puede encontrarse más información sobre los estudios de gemelos en :
+
+ http://www.imm.ki.se/TWIN/TWINUKW.HTM
+
+La última parte del proyecto se administra con un interfaz web escrito usando Perl y MySQL.
+Cada noche, todos los datos de las entrevistas son movidos a una base de datos MySQL.
+
+8.6.1 Buscar todos los gemelos no-distribuidos
+
+La siguiente consulta se usa para determinar quién pasa a la segunda parte del proyecto:
+
+ select
+ concat(p1.id, p1.tvab) + 0 as tvid,
+ concat(p1.christian_name, " ", p1.surname) as Name,
+ p1.postal_code as Code,
+ p1.city as City,
+ pg.abrev as Area,
+ if(td.participation = "Aborted", "A", " ") as A,
+ p1.dead as dead1,
+ l.event as event1,
+ td.suspect as tsuspect1,
+ id.suspect as isuspect1,
+ td.severe as tsevere1,
+ id.severe as isevere1,
+ p2.dead as dead2,
+ l2.event as event2,
+ h2.nurse as nurse2,
+ h2.doctor as doctor2,
+ td2.suspect as tsuspect2,
+ id2.suspect as isuspect2,
+ td2.severe as tsevere2,
+ id2.severe as isevere2,
+ l.finish_date
+ from
+ twin_project as tp
+ /* For Twin 1 */
+ left join twin_data as td on tp.id = td.id and tp.tvab = td.tvab
+ left join informant_data as id on tp.id = id.id and tp.tvab = id.tvab
+ left join harmony as h on tp.id = h.id and tp.tvab = h.tvab
+ left join lentus as l on tp.id = l.id and tp.tvab = l.tvab
+ /* For Twin 2 */
+ left join twin_data as td2 on p2.id = td2.id and p2.tvab = td2.tvab left join informant_data as id2 on p2.id = id2.id and p2.tvab = id2.tvab
+ left join harmony as h2 on p2.id = h2.id and p2.tvab = h2.tvab
+ left join lentus as l2 on p2.id = l2.id and p2.tvab = l2.tvab,
+ person_data as p1,
+ person_data as p2,
+ postal_groups as pg
+ where
+ /* p1 gets main twin and p2 gets his/her twin. */
+ /* ptvab is a field inverted from tvab */
+ p1.id = tp.id and p1.tvab = tp.tvab and
+ p2.id = p1.id and p2.ptvab = p1.tvab and
+ /* Just the sceening survey */
+ tp.survey_no = 5 and
+ /* Skip if partner died before 65 but allow emigration (dead=9) */
+ (p2.dead = 0 or p2.dead = 9 or
+ (p2.dead = 1 and
+ (p2.death_date = 0 or
+ (((to_days(p2.death_date) - to_days(p2.birthday)) / 365)
+ >= 65))))
+ and
+ (
+ /* Twin is suspect */
+ (td.future_contact = 'Yes' and td.suspect = 2) or
+ /* Twin is suspect - Informant is Blessed */
+ (td.future_contact = 'Yes' and td.suspect = 1 and id.suspect = 1) o
+ /* No twin - Informant is Blessed */
+ (ISNULL(td.suspect) and id.suspect = 1 and id.future_contact = 'Yes') or
+ /* Twin broken off - Informant is Blessed */
+ (td.participation = 'Aborted'
+ and id.suspect = 1 and id.future_contact = 'Yes') or
+ /* Twin broken off - No inform - Have partner */
+ (td.participation = 'Aborted' and ISNULL(id.suspect) and p2.dead = 0))
+ and
+ l.event = 'Finished'
+ /* Get at area code */
+ and substring(p1.postal_code, 1, 2) = pg.code
+ /* Not already distributed */
+ and (h.nurse is NULL or h.nurse=00 or h.doctor=00)
+ /* Has not refused or been aborted */
+ and not (h.status = 'Refused' or h.status = 'Aborted'
+ or h.status = 'Died' or h.status = 'Other')
+ order by
+ tvid;
+
+Algunas explicaciones:
+
+`concat(p1.id, p1.tvab) + 0 as tvid'
+ Queremos ordenar por la concatenación de `id' y `tvab' en orden numérico.
+ Añadiendo `0' al resultado provocamos que *MySQL* trate el resultado como
+ un número.
+
+column `id'
+ Esto identifica un par de gemelos. Es una clave en todas las tablas.
+
+column `tvab'
+ Esto identifica un gemelo de una pareja. Tiene un valor de `1' ó `2'
+
+column `ptvab'
+ Esto es la inversa de `tvab'. Cuando `tvab' es `1' esto es `2', y
+ vice versa. Esto existe para ahorrarnos teclear y para hacer más fácil
+ la optimización de la consulta a MySQL.
+
+
+Esta consulta demuestra, entre otras cosas, cómo realizar búsquedas en una tabla
+enlazada con la misma tabla a través de un join (p1 y p2). En el ejemplo, ésto
+se usa para comprobar cuándo un gemelo de una pareja murió antes de cumplir 65.
+En caso afirmativo, la fila no es devuelta.
+
+Todo lo anterior existe en todas las tablas con información relacionada con los gemelos.
+Tenemos una clave tanto en id, tvab (todas las tablas) como en id,ptvab (person_data) para
+construir consultas más rápidas.
+
+En nuestra máquina de producción (una UltraSPARC 200MHz), esta consulta devuelve alrededor
+de 150-200 filas y tarda menos de un segundo.
+
+El número actual de registros en las tablas usadas arriba:
+
+Tabla Filas
+
+person_data 71074
+lentus 5291
+twin_project 5286
+twin_data 2012
+informant_data 663
+harmony 381
+postal_groups 100
+
+
+
+
+8.6.2 Mostrar una tabla con el estado de la pareja de gemelos.
+
+Cada entrevista finaliza con un código de estado llamado event. La consulta mostrada
+debajo se usa para imprimir una tabla sobre todas las parejas de gemelos combinadas por evento.
+Esto indica en cuántas parejas ambos gemelos han finalizado, en cuántas parejas
+ha finalizado un gemelo y el otro se rechazó, etc.
+
+ select
+ t1.event,
+ t2.event,
+ count(*)
+ from
+ lentus as t1,
+ lentus as t2,
+ twin_project as tp
+ where
+ /* We are looking at one pair at a time */
+ t1.id = tp.id
+ and t1.tvab=tp.tvab
+ and t1.id = t2.id
+ /* Just the sceening survey */
+ and tp.survey_no = 5
+ /* This makes each pair only appear once */
+ and t1.tvab='1' and t2.tvab='2'
+ group by
+ t1.event, t2.event;
+
+
+
diff --git a/Docs/internals.texi b/Docs/internals.texi
new file mode 100644
index 00000000000..01f5b0a346c
--- /dev/null
+++ b/Docs/internals.texi
@@ -0,0 +1,134 @@
+\input texinfo @c -*-texinfo-*-
+@c Copyright 1998 TcX AB, Detron HB and Monty Program KB
+@c
+@c %**start of header
+@setfilename internals.info
+@c We want the types in the same index
+@c @synindex tp fn cp
+@synindex cp fn
+@iftex
+@c Well this is normal in Europe. Maybe this shold go into the include.texi?
+@afourpaper
+@end iftex
+@c Get version and other info
+@include include.texi
+@ifclear tex-debug
+@c This removes the black squares in the right margin
+@finalout
+@end ifclear
+@c Set background for HTML
+@set _body_tags BGCOLOR=#FFFFFF TEXT=#000000 LINK=#101090 VLINK=#7030B0
+@settitle @strong{MySQL} internals Manual for version @value{mysql_version}.
+@setchapternewpage off
+@c %**end of header
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* mysql-internals: (mysql-internals). @strong{MySQL} internals.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@titlepage
+@sp 10
+@center @titlefont{@strong{MySQL} Internals Manual.}
+@sp 10
+@center Copyright @copyright{} 1998 TcX AB, Detron HB and Monty Program KB
+@end titlepage
+
+@node Top, Introduction, (dir), (dir)
+
+@ifinfo
+This is a manual about @strong{MySQL} internals.
+@end ifinfo
+
+@menu
+@end menu
+
+@node caching
+@chapter How do MySQL handle caching
+
+MySQL has the following caches:
+(Note that the some of the filename has wrong spelling of cache :)
+
+@itemize @bullet
+@item Key cache
+A shared cache for all B-tree index blocks in the different NISAM
+files. Uses hashing and reverse linked lists for quick caching of the
+last used blocks and quick flushing of changed entries for a specific
+table. mysys/mf_keycash.c
+
+@item Record cache
+This is used for quick scanning of all records in a table.
+mysys/mf_iocash.c and isam/_cash.c
+
+@item Table cache
+This holds the last used tables. sql/sql_base.cc
+
+@item Hostname cache
+For quick lookup (with reverse name resolving). Is a must when one has a
+slow DNS. sql/hostname.cc
+
+@item Privilege cache
+To allow quick change between databases the last used privileges are
+cached for each user/database combination. sql/sql_acl.cc
+
+@item Heap table cache
+Many use of GROUP BY or DISTINCT caches all found
+rows in a HEAP table (this is a very quick, in memory table with hash index)
+
+@item Join row cache.
+For every full join in a SELECT statement (a full join here means there
+was no keys that one could use to find the next table in a list), the
+found rows are cached in a join cache. One SELECT query can use many
+join caches in the worst case.
+@end itemize
+
+@node flush tables
+@chapter How do MySQL handle flush tables
+
+@itemize @bullet
+@item
+Flush tables is handled in sql/sql_base.cc::close_cached_tables().
+@Item
+The idea of flush tables is to force all tables to be closed. This
+is mainly to ensure that if someone adds a new table outside of
+MySQL (for example with 'cp') all threads will start using the new table.
+This will also ensure that all table changes are flushed to disk
+(but of course not as optimally as simple calling a sync on all tables)!
+@item
+When one does a 'flush tables', the variable 'refresh_version' will
+be incremented. Every time a thread releases a table it checks if
+the refresh version of the table (updated at open) is the same as
+the current refresh_version. If not it will close it and broadcast
+a signal on COND_refresh (to wait any thread that is waiting for
+all instanses of a table to be closed).
+@item
+The current refresh_version is also compared to the open refresh_version
+after a thread gets a lock on a table. If the refresh version is
+different the thread will free all locks, reopen the table and try
+to get the locks again; This is just to quickly get all tables to
+use the newest version. This is handled by
+sql/lock.cc::mysql_lock_tables() and sql/sql_base.cc::wait_for_tables().
+@item
+When all tables has been closed flush-tables will return an ok to client.
+@item
+If the thread that is doing flush-table has a lock on some tables,
+it will first closes the locked tables, wait until all other threads
+have also closed these and then reopen these and get the locks.
+After this it will give other threads a possibility to open the
+same tables.
+@end itemize
+
+@node Index
+@unnumbered Index
+
+@printindex fn
+
+@summarycontents
+@contents
+
+@bye
+
+Do text here do something ??
diff --git a/Docs/manual-license-spanish.texi b/Docs/manual-license-spanish.texi
new file mode 100644
index 00000000000..c9cf2bd53da
--- /dev/null
+++ b/Docs/manual-license-spanish.texi
@@ -0,0 +1,709 @@
+@cindex Licensing terms
+@cindex Support terms
+@node Licensing and Support, Installing, Questions, Top
+@chapter MySQL licensing and support
+
+@menu
+* Licensing policy:: Política de licenciamento do @strong{MySQL}
+* Copyright:: Direitos autorais usados por @strong{MySQL}
+* Commercial use:: Distribuindo comercialmente @strong{MySQL}
+* Licensing examples:: Exemplos de situações de licenciamento
+* Cost:: Preços de licenciamento e suporte @strong{MySQL}
+* Support:: Tipos de suporte comercial
+@end menu
+
+Este capítulo descreve os tipos de licenciamento e suporte do @strong{MySQL}, incluindo:
+
+@itemize @bullet
+@item
+Nossa política de licenciamento para sistemas operacionais não Microsoft e Microsoft
+
+@item
+Os direitos autorais sob os quais o @strong{MySQL} é distribuído
+(@pxref{Copyright})
+
+@item
+Exemplo de situações quando uma licença é necessária
+(@pxref{Licensing examples})
+
+@item
+Preços de licenciamento e suporte (@pxref{Cost}), e
+benefícios do suporte (@pxref{Support})
+@end itemize
+
+@cindex Licensing policy
+@node Licensing policy, Copyright, Licensing and Support, Licensing and Support
+@section MySQL licensing policy
+
+Os termos formais do licenciamento para sistemas operacionais não Microsoft tais como
+Unix ou OS/2 são especificados em @ref{Public license}. Basicamente, nossa política de
+licenciamento é como segue:
+
+@itemize @bullet
+@item
+Para uso interno normal, o @strong{MySQL} geralmente não custa nada. Você não precisa
+nos pagar se não o quiser.
+
+@item
+Uma licença é requerida se:
+
+@itemize @minus
+@item
+Você vende o servidor @strong{MySQL} diretamente ou como parte de outro produto ou serviço.
+
+@item
+Você cobra para instalar e manter um servidor @strong{MySQL} no local do cliente
+
+@item
+Você incluie o @strong{MySQL} numa distribuição que não é redistribuída
+e você cobra por alguma parte dessa distribuição
+@end itemize
+
+@item
+Para circunstâncias sob as quais uma licença do @strong{MySQL} é requerida,
+você necessita uma licença por mâquina que roda o servidor @code{mysqld}.
+Entretanto, uma mâquina com múltiplos processadores conta como uma mâquina
+simples e não há restrição no número de servidores que rodam numa só mâquina
+ou no número de clientes concurrentes conectados ao servidor em essa mâquina.
+
+@item
+Você não necessita uma licença para incluir código de programas clientes
+comerciais. O acesso de parte de clientes para o @strong{MySQL} é de
+domínio público. O código do cliente @code{mysql} de linha de comando
+incluie código da livraria @code{readline} que está sob a licença pública
+GNU.
+
+@item
+@cindex @code{myisampack}
+Para clientes que tem comprado 1 licença ou suporte MySQL, nós fornecemos
+funcionalidade adicional. Atualmente, isso significa o fornecimento do
+utilitário @code{myisampack} para banco de dados somente de leitura,
+rápidos e compactados. (O servidor incluie suporte para ler tais bancos
+de dados mas não a ferramenta de compactar usada para criar os mesmos).
+Quando os acordos de suporte gerem suficientes recursos, nós liberaremos
+esta ferramenta sob a mesma licença do servidor @strong{MySQL}.
+
+@item
+Se seu uso do @strong{MySQL} não requer uma licença, porém você gosta
+do @strong{MySQL} e deseja encorajar um maior desenvolvimento, você é
+certamente bem-vindo a adquirir uma licença de qualquer forma.
+
+@item
+Se usa o @strong{MySQL} num contexto comercial de tal forma
+que obtêm benefícios no seu uso, nós lhe solicitamos que apoie
+o desenvolvimento do @strong{MySQL} através da compra de algum
+nível de suporte. Nós achamos que se o @strong{MySQL} o ajuda
+em seu negócio, é razoável que solicitemos sua ajuda para o @strong{MySQL}.
+Por outro lado, se você nós faz perguntas de suporte, não somente está
+usando de graça algo no qual nós colocamos um enorme trabalho, você
+também está pedindo suporte de graça.
+@end itemize
+
+Para uso em sistemas operacionais Microsoft (Win95/Win98/WinNT),
+você precisa de uma licença @strong{MySQL} depois de 30 dias
+de experiência, com a exceção que licenças podem ser requeridas
+sem nenhum custo para uso educacional ou para suportar pesquisas
+de governo ou universidades. @xref{Winlicense}.
+Uma versão shareware do @strong{MySQL}-Win32 que você pode experimentar
+antes de comprar está disponível em @uref{http://www.mysql.com/mysql_w32.htmy}.
+Depois que você tenha pago, você terá uma senha que permite seu acesso a uma
+nova versão @strong{MySQL}-Win32.
+
+Se você tem uma pergunta se for o caso ou não de requerer uma licença para
+seu caso em particular do @strong{MySQL}, favor entrar em contato com nós.
+@xref{Contact information}.
+
+Se você requer uma licença @strong{MySQL}, a forma mais fácil para pagar
+a mesma é usar o formulário no seguro servidor TcX em @url{https://www.mysql.com/license.htmy}.
+Outras formas de pagamento são mencionadas em @ref{Payment information}.
+
+@cindex Copyright
+@node Copyright, Commercial use, Licensing policy, Licensing and Support
+@section Copyrights used by MySQL
+
+@menu
+* Copyright changes:: Possível futura mudança no direito autoral
+@end menu
+
+Existem vários direitos autorais diferentes na distribuição @strong{MySQL}:
+
+@enumerate
+@item
+
+O fonte específico @strong{MySQL}necessário para construir o @code{mysqlclient}
+livrarias e programas no diretório @file{client} está em domínio público.
+Cada arquivo que está em domínio público tem um cabeçalho que claramente notifica
+este estado. Isto incluie tudo no diretório @file{client}e algumas partes
+do @code{mysys}, @code{mystring} e @code{dbug} livrarias.
+
+@item
+Algumas pequenas partes do fonte (GNU @code{getopt}) estão cobertas pela
+``GNU LIBRARY LIBRARY GENERAL PUBLIC LICENSE''. Ver o arquivo
+@file{mysys/COPYING.LIB}.
+
+@item
+Algumas pequenas partes do fonte ( (GNU @code{readline}) estão cobertas pela
+``GNU GENERAL PUBLIC LICENSE''. Ver o arquivo @file{readline/COPYING}.
+
+@item
+Algumas partes do fonte (a @code{regexp} livraria) está coberta pelo estilo de
+direito autoral Berkeley.
+
+@item
+O outro fonte necessário para o servidor @strong{MySQL} em plataformas não Microsoft
+está coberta pela ``MySQL FREE PUBLIC LICENSE'', a qual é baseada na
+``Aladdin FREE PUBLIC LICENSE.'' @xref{Public license}. Quando o @strong{MySQL}
+está rodando em qualquer sistema operacional Microsoft, outro licenciamento é aplicado.
+@end enumerate
+
+Os seguintes pontos direcionam a filosofia sob nossa política de direito autoral:
+
+@itemize @bullet
+@item
+A livraria cliente SQL deve ser totalmente livre tal que a mesma pode ser incluída
+em produtos comerciais sem nenhuma limitação.
+
+@item
+Pessoas que querem livre acesso ao programa no qual nós temos colocado uma grande
+quantidade de trabalho, podem tê-lo, tal que não procurem ganhar dinheiro diretamente
+pela distribuição e para benefício.
+
+@item
+Pessoas que querem manter o direito da propriedade de seu programa, porém também
+querem o valor de nosso trabalho, podem pagar pelo previlégio.
+
+@item
+O uso normal em casa é de GRAÇA. Mas se você usa o @strong{MySQL} para algo
+importante para você, você pode ajudar o desenvolvimento futuro pela
+compra de uma licença ou contrato de suporte.@xref{Support}.
+@end itemize
+
+@node Copyright changes, , Copyright, Copyright
+@subsection Possible future copyright changes
+
+Nós poderemos optar para distribuir versões antigas do @strong{MySQL}
+com a GPL no futuro. Entretanto, essas versões devem ser identificadas
+como @strong{GNU MySQL}. Também, todas notas de direitos autorais dos
+arquivos relativos devem ser mudados para a GPL.
+
+@node Commercial use, Licensing examples, Copyright, Licensing and Support
+@section Distributing MySQL commercially
+
+Esta seção é um esclarecimento dos termos de licença que são a base na
+``MySQL FREE PUBLIC LICENSE'' (FPL). @xref{Public license}.
+
+O @strong{MySQL} pode ser @strong{usado} livremente , incluindo
+entidades comerciais para avaliação ou uso interno sem suporte.
+Entretanto, @strong{distribuição} para propósitos comerciais
+do @strong{MySQL}, ou qualquer coisa contendo ou derivando do @strong{MySQL}
+no seu todo ou parte, requer uma licença comercial escrita da TcX AB,
+a única entidade autorizada para garantir tais licenças.
+
+Você não pode incluir o @strong{MySQL} ``de graça'' num pacote contendo
+qualquer coisa pela qual um pagamento está sendo feito, exceto como
+notado abaixo:
+
+A intenção da exceção providenciada na segunda claúsula da licença é
+para permitir que organizações comerciais operando um servidor FTP ou
+uma agência de notícias possam distribuir livremente o @strong{MySQL},
+desde que:
+
+@enumerate
+@item
+A organização complace com as outras provisões da FPL, a qual
+incluie entre outras coisas um requerimento para distribuir o
+código fonte inteiro do @strong{MySQL} e qualquer outro trabalho
+derivado, e para distribuir a FPL em si junto com @strong{MySQL};
+
+@item
+A única cobrança para abaixar o @strong{MySQL} é a cobrança baseada
+na distribuição do serviço e não numa baseada no contexto da
+informação sendo recebida (ex: a cobrança deverá ser a mesma para
+o recebimento de uma coleção qualquer de bits do mesmo tamanho);
+
+@item
+O servidor ou BBS é acessível para o público em geral, ex. o número de
+telefone ou enedereço IP não é guardado em secreto, e qualquer um pode
+obter acesso para a informação (possivelmente pagando uma inscrição ou
+acesso cobrado que não é dependente ou relacionado para comprar qualquer
+outra coisa).
+@end enumerate
+
+Se você quer para distribuir programas em um contexto comercial que
+incorpora @strong{MySQL} e você @strong{não} quer encontrar essas
+condições, você deve contatar TcX AB para encontrar um licenciamento
+comercial, o qual envolve um pagamento. O único meio legal que
+você pode distribuir @strong{MySQL} ou qualquer coisa contendo @strong{MySQL}
+são pela distribuição do @strong{MySQL} sob os requerimentos da FPL, ou pela
+obtenção de uma licença comercial da TcX AB.
+
+@node Licensing examples, Cost, Commercial use, Licensing and Support
+@section Example licensing situations
+
+@menu
+* Products that use MySQL:: Vendendo produtos que usam @strong{MySQL}
+* MySQL services:: Vendendo serviços relacionados ao @strong{MySQL}
+* ISP:: Serviços de ISP com @strong{MySQL}
+* Web server:: Rodando um servidor web usando o @strong{MySQL}.
+@end menu
+
+Esta seção descreve algumas situações ilustrando se é o caso ou não que
+você deve licençar o servidor @strong{MySQL}. Geralmente esses exemplos
+envolvem o fornecimento do @strong{MySQL} como parte de um produto ou
+serviço que você está vendendo para um cliente, ou requer que o @strong{MySQL}
+seja usado em conjunto com seu produto. Em tais casos, é sua responsabilidade
+para obter uma licença para o cliente se uma é necessária (Este requerimento
+pode ser deixado de lado se seu cliente já tem uma licença @strong{MySQL}.
+Porém, o vendedor deve enviar informação do cliente e o número da licença
+para TcX, e a licença deverá ser completa, não uma licença OEM).
+
+Note que uma simples licença do @strong{MySQL} cobre qualquer número de
+CPUs/usuários/clientes/servidores @code{mysqld} numa só mâquina!
+
+@node Products that use MySQL, MySQL services, Licensing examples, Licensing examples
+@subsection Selling products that use MySQL
+
+Para determinar caso seja necessário ou não uma licença @strong{MySQL}
+quando vendendo a sua aplicação, você deve perguntar caso seja necessário
+para o funcionamento adequado de sua aplicação a contingência no uso do
+@strong{MySQL} e seja necessário você incluir o @strong{MySQL} com seu
+produto. Existem vários casos a considerar:
+
+@itemize @bullet
+@item
+Sua aplicação precisa do @strong{MySQL} para funcionar adequadamente ?
+
+Se o seu produto precisa do @strong{MySQL}, você necessita uma licença
+para cada mâquina que roda o servidor @code{mysqld}. Por exemplo,
+se você projeta uma aplicação sobre o @strong{MySQL}, então você tem
+feito realmente um produto comercial que necessita do servidor, tal que
+necessita de uma licença.
+
+Se sua aplicação não requer o @strong{MySQL}, você não necessita obter uma
+licença. Por exemplo, se o @strong{MySQL} apenas adiciona uma nova característica
+a seu produto (tal como adicionando loggin a um banco de dados e se o @strong{MySQL}
+é usado no lugar de um arquivo texto), o mesmo entra como um uso normal, e uma
+licença não precisa ser requerida.
+
+Em outras palavras, você necessita de uma licença se você vende um produto
+projetado para uso com o @strong{MySQL} ou que precisa do servidor @strong{MySQL}
+para um funcionamento completo. Isto é verdadeiro caso haja necessidade ou não de fornecer
+o @strong{MySQL} para seu cliente como parte da distribuição de seu produto.
+
+Isso também depende no que você está fazendo para o cliente. Você planeja fornecer
+a seu cliente com instruções e detalhes na instalação do @strong{MySQL} com seu
+programa ?. Então seu produto contencialmente precisa do @strong{MySQL};
+Sim é tal, você necessita comprar uma licença. Se você simplesmente usa um banco de
+dados que espera já estiver instalado no instante en seu programa é comprado, então
+provavelmente não necessita de uma licença.
+
+@item
+Você incluie o @strong{MySQL} numa distribuição e cobra pela mesma ?
+
+Se você incluie @strong{MySQL} com a distribuição que vende para os clientes,
+você necessita uma licença para cada mâquina que roda o servidor @code{mysqld},
+porque neste caso você está vendendo um sistema que incluie @strong{MySQL}.
+
+Isto é verdadeiro no caso que o @strong{MySQL} com seu produto seja requerido
+ou opcional.
+
+@item
+Você não requer nem incluie o @strong{MySQL} com seu produto ?
+
+Suponha que quer vender um produto projetado de uma maneira geral para usar
+com "qualquer banco de dados" e que pode ser configurado para usar qualquer
+uma das várias alternativas de sistemas de banco de dados (@strong{MySQL},
+PostgreSQL, ou qualquer outro. Isto é, seu produto não requer @strong{MySQL},
+mas pode suportar qualquer banco de dados com o nível base de funcionalidade
+e você não depende de qualquer coisa que somente @strong{MySQL} suporta.
+Nenhum de vocês paga para nós se o seu cliente realmente seleciona para
+usar @strong{MySQL}?
+
+Neste caso, se você não fornece, obtêm ou configura o @strong{MySQL} para
+o cliente e decide o cliente para usá-lo, nenhum de vocês precisa de uma
+licença. Se você faz um serviço, vide @ref{MySQL services, ,
+@strong{MySQL} serviços}.
+@end itemize
+
+@node MySQL services, ISP, Products that use MySQL, Licensing examples
+@subsection Selling MySQL-related services
+
+Se você faz uma instalação numa mâquina de um cliente do @strong{MySQL}
+e há cobrança pelo serviço (direta ou indiretamente), então você comprar
+uma licença @strong{MySQL}.
+
+Se você vende uma aplicação para a qual o @strong{MySQL} não é estritamente
+requerido, porém pode ser usado, uma licença deve indicada, dependendo
+como o @strong{MySQL} é configurado. Suponha que seu produto não requera e
+não incluia o @strong{MySQL} na sua distribuição, porém pode ser configurado
+para usar o @strong{MySQL} para os clientes que assim o desejar. (Este pode ser
+o caso, por exemplo, se seu produto pode usar qualquer um de servidores de
+banco de dados).
+
+Se o cliente obtêm e instala o @strong{MySQL}, nenhuma licença é necessária.
+Entretanto, se você faz o serviço para seu cliente, então é necessário uma
+licença, porque você está vendendo um serviço que incluie o @strong{MySQL}.
+
+@node ISP, Web server, MySQL services, Licensing examples
+@subsection ISP MySQL services
+
+Provedores de Serviço Internet (ISPs) às vezes hospedam servidores @strong{MySQL}
+para seus cliente.
+
+Se você é um ISP que permite a seus clientes instalar e administrar o
+@strong{MySQL} por si próprios na sua mâquina sem nenhuma assistência
+de sua parte, nem você nem o cliente precisa de uma licença @strong{MySQL}.
+
+Se você cobra para instalar e administrar o @strong{MySQL} como parte de seu
+serviço para o cliente, então você precisa de uma licença, porque está vendendo
+um serviço que incluie o @strong{MySQL}.
+
+@node Web server, , ISP, Licensing examples
+@subsection Running a web server using MySQL
+
+Se você usa o @strong{MySQL} em conjunto com um servidor web, você não tem
+que pagar uma licença.
+
+Isto é verdadeiro se você roda um servidor web comercial que usa @strong{MySQL},
+desde que você não esteja vendendo o @strong{MySQL}. Entretanto, neste caso
+nós gostariamos que você compre suporte @strong{MySQL}, porque @strong{MySQL}
+está ajudando a sua empresa.
+
+@cindex Costs, licensing and support
+@cindex Licensing costs
+@cindex Support costs
+@node Cost, Support, Licensing examples, Licensing and Support
+@section MySQL licensing and support costs
+
+@menu
+* Payment information:: Informação de Pagamento
+* Contact information:: Informação de contato
+@end menu
+
+Nossos preços atuais de licença são mostrados abaixo. Todos os preços são
+em US Dólar. Se você paga com cartão de crédito, a moeda é o EURO (European Union Euro),
+tais preços diferem levemente.
+
+@multitable @columnfractions .25 .2 .3
+@item @strong{Número de licenças} @tab @strong{Preço por cópia} @tab @strong{Total}
+@item 1 @tab US $200 @tab US $200
+@item 10 pacotes @tab US $150 @tab US $1500
+@item 50 pacotes @tab US $120 @tab US $6000
+@end multitable
+
+Para compras em alto volume (OEM), os seguintes preços são aplicados:
+
+@multitable @columnfractions .25 .2 .3 .25
+@item @strong{Número de licenças} @tab @strong{Preço por cópia} @tab @strong{Mínimo de uma vez} @tab @strong{Pagamento mínimo}
+@item 100-999 @tab US $40 @tab 100 @tab US $4000
+@item 1000-2499 @tab US $25 @tab 200 @tab US $5000
+@item 2500-4999 @tab US $20 @tab 400 @tab US $8000
+@end multitable
+
+Para compras OEM, você deve atuar como o intermediário para eventuais
+problemas ou solicitações de seus usuários. Nós também requeremos que
+clientes OEM tenham ao menos um contrato de suporte extended email.
+
+Se você tem uma margem baixa em alto volume de produtos, você pode falar
+com nós sobre outros termos (por exemplo, a porcentagem dos preços de
+venda). Se você faz, por favor seja informativo sobre seu produto, preço,
+mercado e qualquer outra informação que seja relevante.
+
+@cindex @code{myisampack}
+Depois de comprar 1 licença @strong{MySQL}, você terá uma cópia pessoal
+do utilitário @code{myisampack}. Você não está permitido em distribuir
+esse utilitário porém você pode distribuir tabelas compactadas com ele.
+
+Um preço completo de uma licença não é um acordo de suporte e incluie um
+mínimo suporte. Isto significa que nós tentamos responder qualquer pergunta
+relevante. Se a resposta está na documentação, nós direcionamos você à
+apropriada seção. Se você não tem comprado uma licença ou suporte, nós
+provavelmente não responderemos ao tudo.
+
+Se você descobre o que consideramos um real bug, nós estamos prontificados
+a solucionar o erro em qualquer caso. Porém se você paga por suporte nós
+o notificaremos sobre o andamento da solução ao invés de soluncioná-lo
+nos próximos lançamentos.
+
+Suporte mais amplo é vendido separadamente. Descrições do que incluie cada
+nível de suporte são dadas em @ref{Support}. Custos para os vários tipos
+comerciais de suporte são mostrados abaixo. O nível de preços de suporte
+estão em EURO (European Union Euro). Um EURO é aproximadamente 1.17 USD.
+
+@multitable @columnfractions .3 .3
+@item @strong{Tipo de suporte} @tab @strong{Custo por ano}
+@item Basic email support @tab EURO 170
+@item Extended email support @tab EURO 1000
+@item Login support @tab EURO 2000
+@item Extended login support @tab EURO 5000
+@end multitable
+
+Você pode atualizar um nível mais baixo sw suporte para um de maior
+nível, pela diferença entre os preços dos dois níveis.
+
+@cindex Payment information
+@node Payment information, Contact information, Cost, Cost
+@subsection Payment information
+
+Correntemente nós podemos tomar pagamentos SWIFT, cheques ou cartões de crédito.
+
+O pagamento poderá ser feito a:
+@example
+Postgirot Bank AB
+105 06 STOCKHOLM, SWEDEN
+
+TCX DataKonsult AB
+BOX 6434
+11382 STOCKHOLM, SWEDEN
+
+SWIFT address: PGSI SESS
+Número da Conta: 96 77 06 - 3
+@end example
+
+Especificar: licença e/ou suporte, seu nome e endereço de e-mail.
+
+Em europa e Japão você pode usar EuroGiro (que pode ser menos caro) para a mesma
+conta.
+
+Se você quer pagar através de cheque, faça-o nominal a ``Monty Program KB'' e mande
+um e-mail para o endereço abaixo:
+
+@example
+TCX DataKonsult AB
+BOX 6434, Torsgatan 21
+11382 STOCKHOLM, SWEDEN
+@end example
+
+Se você quer pagar com cartão de crédito usando a Internet, você pode
+usar o seguro formulário de licença da TcX:
+@uref{https://www.mysql.com/license.htmy.
+
+Você pode também imprimir uma cópia do formulário de licença, prenché-lo e mandá-lo
+via fax para:
+
+
++46-8-729 69 05
+
+Se você quer que nós uma cobrança para você, você pode usar o formulário de
+licença e escrever ``bill us'' no campo de comentários. Você pode também
+mandar uma mensagem via e-mail para @email{sales@@mysql.com} (@strong{not}
+@email{mysql@@lists.mysql.com}!) com a informação de sua companhia e pedir
+para nós para efetuar a cobrança.
+
+@cindex Contact information
+@node Contact information, , Payment information, Cost
+@subsection Contact information
+
+Para licenciamento comercial, ou se você têm qualquer pergunta sobre
+informação desta seção, por favor contatar a equipe de licenciamento
+do @strong{MySQL}. O mais preferido método é o e-mail para
+@email{mysql-licensing@@mysql.com}. Fax é também possível porém sua
+manipulação pode demorar muito (Fax +46-8-729 69 05).
+
+@example
+David Axmark
+Detron HB
+Kungsgatan 65 B
+753 21 UPPSALA
+SWEDEN
+Fone Voz +46-18-10 22 80 (Timezone GMT+1. Fala Sueco e Inglés)
+@end example
+
+@cindex Support, types
+@cindex Types of support
+@node Support, , Cost, Licensing and Support
+@section Types of commercial support
+
+@menu
+* Basic email support:: Basic email support
+* Extended email support:: Extended email support
+* Login support:: Login support
+* Extended login support:: Extended login support
+@end menu
+
+@node Basic email support, Extended email support, Support, Support
+@subsection Basic email support
+
+Basic email support é a opção mais barata de suporte e deverá ser vista
+como uma forma de suportar nosso desenvolvimento do @strong{MySQL} que
+uma real opção de suporte.
+
+Neste nível de suporte, a lista de e-mail do @strong{MySQL} é o preferido
+meio de comunicação. Perguntas normalmente podem ser enviadas para a
+principal lista de e-mail (@email{mysql@@lists.mysql.com}) ou uma das outras
+listas regulares (por exemplo, @email{mysql-win32@@lists.mysql.com} relacionada
+às perguntas para o @strong{MySQL} Windows, tal que qualquer pessoa pode já ter
+experimentado e resolvido o problema que você tem. @xref{Asking questions}.
+
+Entretanto, comprando o suporte basic email support, você também tem acesso
+ao e-mail @email{mysql-support@@mysql.com}, o qual não é disponível
+como parte do suporte mínimo que se tem quando se adquire uma licença @strong{MySQL}.
+Isto significa que para perguntas críticas, você pode mandar sua mensagem para
+@email{mysql-support@@mysql.com}. (Se a mensagem tem dados privados, você só
+deve mandar para o @email{mysql-support@@mysql.com}.)
+
+@emph{LEMBRE-SE!} para SEMPRE incluir o número de registro e data de
+término quando mandar uma mensagem para
+@email{mysql-support@@mysql.com}.
+
+Basic email support incluie os seguintes tipos de serviços:
+
+@itemize @bullet
+@item
+Se sua pergunta já está respondida no manual, nós o informamos da correta
+seção na qual pode encontrar a resposta. Se a resposta não está no manual,
+nós o colocamos na direção certa para resolver seu problema.
+
+@item
+Nós garantimos em tempo apropriado a resposta das mensagem de seu e-mail.
+Nós não podemos garantir que podemos resolver qualquer problema, porém ao
+menos você receve uma resposta se podemos contatá-lo por e-mail.
+
+@item
+Nós podemos ajudá-lo com problemas inesperados quando instala @strong{MySQL}
+a partir de uma distribuição binária em plataformas suportadas. Este nível de
+suporte não cobre instalação do @strong{MySQL} a partir de uma distribuição
+fonte. Plataformas ``Suportadas'' são aquelas plataformas nas quais o @strong{MySQL}
+é conhecido que funciona.
+@xref{Which OS}.
+
+@item
+Nós ajudaremos você com bugs e problemas de características. Qualquer
+bug que for encontrado nós o solucionamos no próximo lançamento do @strong{MySQL}.
+Se o bug é crítico para você, nós enviamos um e-mail com o patch
+tão logo como o bug é resolvido. Bugs críticos têm sempre para nós a maior
+prioridade, para assegurar que sejam solucionados tão pronto como possível.
+
+@item
+Suas sugestões para desenvolvimento posterior do @strong{MySQL} são tomadas
+em consideração. Obtendo o email support, você já ajuda o desenvolvimento
+posterior do @strong{MySQL}. Se você quer pôr mais, faça a atualização
+para um nível mais alto de suporte.
+
+@item
+Se você quer nós ajudar a otimizar seu sistema, você deve atualizar
+para um nível maior de suporte.
+
+@item
+@cindex @code{myisampack}
+Nós incluimos uma versão binária da ferramenta de compactação @code{myisampack}
+para criar rápidos bancos de dados compactados, somente de leitura. O atual
+servidor incluie suporte para ler esses bancos de dados mas não a ferramenta
+para criar os mesmos.
+@end itemize
+
+@node Extended email support, Login support, Basic email support, Support
+@subsection Extended email support
+
+Extended email support incluie tudo o do basic email support com estas
+adições:
+
+@itemize @bullet
+@item
+Seu e-mail será tratado antes dos e-amil dos usuários do basic email support
+e dos usuários não registrados.
+
+@item
+Suas sugestões para o próximo desenvolvimento do @strong{MySQL} receberá
+uma forte consideração. Simples extensões que fazem os gols do @strong{MySQL}
+são a implementação em questão de dias. adquirindo o extended email support
+você auxilia daqui para frente o desenvolvimento do @strong{MySQL}.
+
+@item
+Perguntas típicas que são cobertas pelo extended email support são:
+
+@itemize @minus
+@item
+Nós respondemos e (dentro do razoável) resolvemos as perguntas relacionadas
+a possíveis bugs no @strong{MySQL}. Tão pronto como os bugs são encontrados
+e corregidoa, nós mandamos por e-mail o pacth para ele.
+
+@item
+Nós auxiliamos com inesperados problemas quando você instala o @strong{MySQL}
+a partir do fonte ou distribuição binária nas plataformas suportadas.
+
+@item
+Nós responderemos perguntas sobre características perdidad e ofereceremos
+dicas como trabalhar e contornar elas.
+
+@item
+Nós forneceremos dicas na otimização do @code{mysqld}para sua situação.
+@end itemize
+
+@item
+Você está permitido a influenciar a prioridade de itens do TODO do @strong{MySQL}.
+Isso assegura que as características que você realmente precisa sejam implementadas
+rapidamente que as mesmas poderia ser de outra forma.
+@end itemize
+
+@node Login support, Extended login support, Extended email support, Support
+@subsection Login support
+
+O Login support incluie tudo do extended email support com estas adições:
+
+@itemize @bullet
+@item
+Seu e-mail terá prioridade sobre os usuários do suporte extended email.
+
+@item
+Suas sugestões para o próximo desenvolvimento do @strong{MySQL} será tomado
+com uma alta consideração. Extensões reais que podem ser implementadas num
+par de horas e que fazem os gols do @strong{MySQL} serão implementadas
+tão logo como possível.
+
+@item
+Se você tem um problema muito específico, nós tentaremos logar no seu
+sistema para resolver o problema ''no local''.
+
+@item
+Tal como qualquer outro vendedor de banco de dados, não podemos garantir que
+podemos recuperar qualquer dado de tabelas corrompidas, porém se o pior acontece
+nós poderemos a recuperar tanto quanto seja possível. O @strong{MySQL}tem provado
+ser muito seguro, porém qualquer é possível devido a circuntâncias fora de nosso
+controle (por exemplo, se seu sistema crash ou alguém kill o servidor executando
+um comando @code{kill -9}).
+
+@item
+Nós providenciaremos dicas na otimização de seu sistema e consultas.
+
+@item
+Você está permitido para chamar um desenvolvedor @strong{MySQL} (moderadamente) e
+discutir seu problemas relacionados com o @strong{MySQL}.
+@end itemize
+
+@node Extended login support, , Login support, Support
+@subsection Extended login support
+
+O Extended login support incluie tudo do login support com estas adições:
+
+@itemize @bullet
+@item
+Seu e-mail tem a mais alta prioridade possível.
+
+@item
+Nós ativamente examinamos seu sistema e ajudamos a otimizá-lo assim como suas
+consultas. Nós também podemos otimizar e/ou extender o @strong{MySQL}
+para suprir melhor suas necessidades.
+
+@item
+Você também pode solicitar extensões es peciais apenas para você. Por exemplo:
+@example
+mysql> select MY_CALCULATION(col_name1,col_name2) from tbl_name;
+@end example
+
+@item
+Nós podemos fornecer uma distribuição binária para todas as atualizações
+mais importantes do @strong{MySQL} para seu sistema, tão logo como podemos
+obter uma conta em um sistema similar. No pior dos casos, nós podemos requerer
+acesso para seu sistema para ser capaz de criar uma distribuição binária.
+
+@item
+Se você pode providenciar acomodações e pagar os custos de viagem para um
+desenvolvedor @strong{MySQL} para vistá-lo e oferecer ajuda com seus problemas.
+O suporte Extended login support entitula você para um encontro pessoal por
+ano, porém nós sempre somos muito flexíveis para levar para frente nossos
+clientes!.
+@end itemize
+
+@node Installing, Compatibility, Licensing and Support, Top
+
diff --git a/Docs/manual.texi b/Docs/manual.texi
new file mode 100644
index 00000000000..7eebc96a540
--- /dev/null
+++ b/Docs/manual.texi
@@ -0,0 +1,41455 @@
+\input texinfo @c -*-texinfo-*-
+@c Copyright 1997, 1998, 1999, 2000 TcX AB, Detron HB and MySQL Finland AB
+@c
+@c *********************************************************
+@c Note that @node names are used on our Website.
+@c So do not change node names without checking
+@c Makefile.am and SitePages first.
+@c *********************************************************
+@c
+@c %**start of header
+@setfilename mysql.info
+@c We want the types in the same index
+@syncodeindex tp fn
+@c Get version info. This file is generated by the Makefile!!
+@include include.texi
+@ifclear tex-debug
+@c This removes the black squares in the right margin
+@finalout
+@end ifclear
+@c Set background for HTML
+@set _body_tags BGCOLOR=silver TEXT=#000000 LINK=#101090 VLINK=#7030B0
+@c Set some style elements for the manual in HTML form. 'suggested'
+@c natural language colours: aqua, black, blue, fuchsia, gray, green,
+@c lime, maroon, navy, olive, purple, red, silver, teal, white, and
+@c yellow. From Steeve Buehler <ahr@YogElements.com>
+@set _extra_head <style> code {color:purple} tt {color:green} samp {color:navy} pre {color:maroon} </style>
+@settitle @strong{MySQL} Reference Manual for version @value{mysql_version}.
+@c We want single-sided heading format, with chapters on new pages. To
+@c get double-sided format change 'on' below to 'odd'
+@setchapternewpage on
+@paragraphindent 0
+@c %**end of header
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* mysql: (mysql). @strong{MySQL} documentation.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@titlepage
+@sp 10
+@center @titlefont{@strong{MySQL} Reference Manual}
+@sp 10
+@center Copyright @copyright{} 1997, 1998, 1999, 2000 TcX AB, Detron HB and MySQL Finland AB
+@end titlepage
+
+@c This should be added. The HTML conversion also needs a MySQL version
+@c number somewhere.
+
+@iftex
+@c change this to double if you want formatting for double-sided
+@c printing
+@headings single
+@everyheading @thispage @| @| @thischapter
+@everyfooting @| @| Version: @value{mysql_version} Printed: @today{}
+@end iftex
+
+@node Top, Introduction, (dir), (dir)
+
+@c @ifhtml
+@c <IMG SRC="Images/mysql-logo.gif">
+@c <!--Image doesn't exist. Can't find suitable replacement. (Matt) -->
+@c @end ifhtml
+
+@ifinfo
+This is a manual for @strong{MySQL}. This version is about the
+@value{mysql_version} version of @strong{MySQL}. For a @strong{3.20}
+version see the relevant distribution.
+@end ifinfo
+
+@menu
+* Introduction:: General Information about @strong{MySQL}
+* Questions:: @strong{MySQL} mailing lists and how to ask questions or report errors (bugs)
+* Licensing and Support:: @strong{MySQL} licensing and support
+* Installing:: Installing @strong{MySQL}
+* Compatibility:: How standards-compatible is @strong{MySQL}?
+* Privilege system:: The @strong{MySQL} access privilege system
+* Reference:: @strong{MySQL} language reference
+* Table types:: @strong{MySQL} table types
+* Tutorial:: @strong{MySQL} Tutorial
+* Server:: @strong{MySQL} Server
+* Replication:: Replication
+* Performance:: Getting maximum performance from @strong{MySQL}
+* MySQL Benchmarks:: The @strong{MySQL} benchmark suite
+* Tools:: @strong{MySQL} Utilities
+* Maintenance:: Maintaining a @strong{MySQL} installation
+* Adding functions:: Adding new functions to @strong{MySQL}
+* Adding procedures:: Adding new procedures to @strong{MySQL}
+* ODBC:: @strong{MySQL} ODBC Support
+* Common programs:: Using @strong{MySQL} with some common programs
+* Problems:: Problems
+* Common problems:: Solving some common problems with @strong{MySQL}
+* Clients:: @strong{MySQL} client tools and APIs
+* Comparisons:: How does @strong{MySQL} compare with other databases?
+* MySQL internals:: @strong{MySQL} internals
+* Environment variables:: @strong{MySQL} environment variables
+* Users:: Some @strong{MySQL} users
+* Contrib:: Contributed programs
+* Credits:: Contributors to @strong{MySQL}
+* News:: @strong{MySQL} change history
+* Bugs:: Known errors and design deficiencies in @strong{MySQL}
+* TODO:: List of things we want to add to @strong{MySQL} in the future (The TODO)
+* Porting:: Comments on porting to other systems
+* Regexp:: Description of @strong{MySQL} regular expression syntax
+* Unireg:: What is Unireg?
+* GPL license:: GNU General Public License
+* LGPL license:: GNU Library General Public License
+* Function Index:: SQL command, type and function index
+* Concept Index:: Concept Index
+
+@detailmenu --- The Detailed Node Listing ---
+
+General Information about MySQL
+
+* What-is:: What is @strong{MySQL}?
+* Manual-info:: About this manual
+* History:: History of @strong{MySQL}
+* MySQL-Books:: Books about MySQL
+* Features:: The main features of @strong{MySQL}
+* Stability:: How stable is @strong{MySQL}?
+* Year 2000 compliance:: Year 2000 compliance
+* General-SQL:: General SQL information and tutorials
+* Useful Links:: Useful @strong{MySQL}-related links
+
+About this manual
+
+* Manual conventions:: Conventions used in this manual
+
+MySQL mailing lists and how to ask questions or report errors (bugs)
+
+* Mailing-list:: The @strong{MySQL} mailing lists
+* Asking questions:: Asking questions or reporting bugs
+* Bug reports:: How to report bugs or problems
+* Answering questions:: Guidelines for answering questions on the mailing list
+
+MySQL licensing and support
+
+* Licensing policy:: @strong{MySQL} licensing policy
+* Copyright:: Copyrights used by @strong{MySQL}
+* Licensing examples:: Example licensing situations
+* Cost:: @strong{MySQL} licensing and support costs
+* Support:: Types of commercial support
+
+Copyrights used by MySQL
+
+* Copyright changes:: Possible future copyright changes
+
+Example licensing situations
+
+* Products that use MySQL:: Selling products that use @strong{MySQL}
+* ISP:: ISP @strong{MySQL} services
+* Web server:: Running a web server using @strong{MySQL}.
+
+@strong{MySQL} licensing and support costs
+
+* Payment information:: Payment information
+* Contact information:: Contact information
+
+Types of commercial support
+
+* Basic email support:: Basic email support
+* Extended email support:: Extended email support
+* Login support:: Login support
+* Extended login support:: Extended login support
+
+Installing MySQL
+
+* Getting MySQL:: How to get @strong{MySQL}
+* Which OS:: Operating systems supported by @strong{MySQL}
+* Which version:: Which @strong{MySQL} version to use
+* Many versions:: How and when updates are released
+* Installation layouts:: Installation layouts
+* Installing binary:: Installing a @strong{MySQL} binary distribution
+* Installing source:: Installing a @strong{MySQL} source distribution
+* Compilation problems:: Problems compiling?
+* MIT-pthreads:: MIT-pthreads notes
+* Perl support:: Perl installation comments
+* Source install system issues:: System-specific issues
+* Win32:: Win32 notes
+* OS/2:: OS/2 notes
+* MySQL binaries::
+* Post-installation:: Post-installation setup and testing
+* Upgrade:: Is there anything special to do when upgrading/downgrading @strong{MySQL}?
+
+Installing a MySQL binary distribution
+
+* Linux-RPM:: Linux RPM files
+* Building clients:: Building client programs
+* Binary install system issues:: System-specific issues
+
+System-specific issues
+
+* Binary notes-Linux:: Linux notes
+* Binary notes-HP-UX:: HP-UX notes
+
+Installing a MySQL source distribution
+
+* Quick install:: Quick installation overview
+* Applying patches:: Applying patches
+* configure options:: Typical @code{configure} options
+
+Perl installation comments
+
+* Perl installation:: Installing Perl on Unix
+* ActiveState Perl:: Installing ActiveState Perl on Win32
+* Win32 Perl:: Installing the @strong{MySQL} Perl distribution on Win32
+* Perl support problems:: Problems using the Perl @code{DBI}/@code{DBD} interface
+
+System-specific issues
+
+* Solaris:: Solaris notes
+* Solaris 2.7:: Solaris 2.7 / 2.8 notes
+* Solaris x86:: Solaris x86 notes
+* SunOS:: SunOS 4 notes
+* Linux:: Linux notes (all Linux versions)
+* Alpha-DEC-Unix:: Alpha-DEC-Unix notes
+* Alpha-DEC-OSF1:: Alpha-DEC-OSF1 notes
+* SGI-Irix:: SGI-Irix notes
+* FreeBSD:: FreeBSD notes
+* NetBSD:: NetBSD notes
+* OpenBSD:: OpenBSD 2.5 notes
+* BSDI:: BSD/OS notes
+* SCO:: SCO notes
+* SCO Unixware:: SCO Unixware 7.0 notes
+* IBM-AIX:: IBM-AIX notes
+* HP-UX 10.20:: HP-UX 10.20 notes
+* HP-UX 11.x:: HP-UX 11.x notes
+* MacOSX:: MacOSX notes
+
+Linux notes (all Linux versions)
+
+* Linux-x86:: Linux-x86 notes
+* Linux-RedHat50:: RedHat 5.0 notes
+* Linux-RedHat51:: RedHat 5.1 notes
+* Linux-SPARC:: Linux-SPARC notes
+* Linux-Alpha:: Linux-Alpha notes
+* MKLinux:: MkLinux notes
+* Qube2:: Qube2 Linux notes
+* Linux-Ia64::
+
+BSD/OS notes
+
+* BSDI2:: BSD/OS 2.x notes
+* BSDI3:: BSD/OS 3.x notes
+* BSDI4:: BSD/OS 4.x notes
+
+Win32 notes
+
+* Win32 installation:: Installing @strong{MySQL} on Win32
+* Win95 start:: Starting @strong{MySQL} on Win95 / Win98
+* NT start:: Starting @strong{MySQL} on NT / Win2000
+* Win32 running:: Running @strong{MySQL} on Win32
+* Win32 and SSH:: Connecting to a remote @strong{MySQL} from Win32 with SSH
+* Win32 symbolic links:: Splitting data across different disks under Win32
+* Win32 compiling::
+* Win32 vs Unix:: @strong{MySQL}-Win32 compared to Unix @strong{MySQL}
+
+Post-installation setup and testing
+
+* mysql_install_db:: Problems running @code{mysql_install_db}
+* Starting server:: Problems starting the @strong{MySQL} server
+* Automatic start:: Starting and stopping @strong{MySQL} automatically
+* Command-line options:: Command-line options
+* Option files:: Option files
+
+Is there anything special to do when upgrading/downgrading MySQL?
+
+* Upgrading-from-3.22:: Upgrading from a 3.22 version to 3.23
+* Upgrading-from-3.21:: Upgrading from a 3.21 version to 3.22
+* Upgrading-from-3.20:: Upgrading from a 3.20 version to 3.21
+* Upgrading-to-arch:: Upgrading to another architecture
+
+How standards-compatible is MySQL?
+
+* Extensions to ANSI:: @strong{MySQL} extensions to ANSI SQL92
+* Ansi mode:: Runnning @strong{MySQL} in ANSI mode
+* Differences from ANSI:: @strong{MySQL} differences compared to ANSI SQL92
+* Missing functions:: Functionality missing from @strong{MySQL}
+* Standards:: What standards does @strong{MySQL} follow?
+* Commit-rollback:: How to cope without @code{COMMIT}-@code{ROLLBACK}
+
+Functionality missing from MySQL
+
+* Missing Sub-selects:: Sub-selects
+* Missing SELECT INTO TABLE:: @code{SELECT INTO TABLE}
+* Missing Transactions:: Transactions
+* Missing Triggers:: Triggers
+* Missing Foreign Keys:: Foreign Keys
+* Missing Views:: Views
+* Missing comments:: @samp{--} as the start of a comment
+
+Foreign Keys
+
+* Broken Foreign KEY:: Reasons NOT to use foreign keys
+
+The MySQL access privilege system
+
+* General security:: General security
+* Security:: How to make @strong{MySQL} secure against crackers
+* What Privileges:: What the privilege system does
+* User names:: @strong{MySQL} user names and passwords
+* Connecting:: Connecting to the @strong{MySQL} server
+* Password security:: Keeping your password secure
+* Privileges provided:: Privileges provided by @strong{MySQL}
+* Privileges:: How the privilege system works
+* Connection access:: Access control, stage 1: Connection verification
+* Request access:: Access control, stage 2: Request verification
+* Privilege changes:: When privilege changes take effect
+* Default privileges:: Setting up the initial @strong{MySQL} privileges
+* Adding users:: Adding new user privileges to @strong{MySQL}
+* Passwords:: How to set up passwords
+* Access denied:: Causes of @code{Access denied} errors
+
+MySQL language reference
+
+* Literals:: Literals: how to write strings and numbers
+* Variables:: User variables
+* Column types:: Column types
+* Functions:: Functions
+* CREATE DATABASE:: @code{CREATE DATABASE} syntax
+* DROP DATABASE:: @code{DROP DATABASE} syntax
+* CREATE TABLE:: @code{CREATE TABLE} syntax
+* ALTER TABLE:: @code{ALTER TABLE} syntax
+* DROP TABLE:: @code{DROP TABLE} syntax
+* OPTIMIZE TABLE:: @code{OPTIMIZE TABLE} syntax
+* CHECK TABLE:: @code{CHECK TABLE} syntax
+* ANALYZE TABLE::
+* REPAIR TABLE:: @code{REPAIR TABLE} syntax
+* DELETE:: @code{DELETE} syntax
+* SELECT:: @code{SELECT} syntax
+* JOIN:: @code{JOIN} syntax
+* INSERT:: @code{INSERT} syntax
+* REPLACE:: @code{REPLACE} syntax
+* LOAD DATA:: @code{LOAD DATA INFILE} syntax
+* UPDATE:: @code{UPDATE} syntax
+* USE:: @code{USE} syntax
+* FLUSH:: @code{Flush} syntax (clearing caches)
+* KILL:: @code{KILL} syntax
+* SHOW:: @code{SHOW} syntax (Get information about tables, columns, ...)
+* EXPLAIN:: @code{EXPLAIN} syntax (Get information about a @code{SELECT})
+* DESCRIBE:: @code{DESCRIBE} syntax (Get information about names of columns)
+* COMMIT:: @code{BEGIN/COMMIT/ROLLBACK} syntax
+* LOCK TABLES:: @code{LOCK TABLES/UNLOCK TABLES} syntax
+* SET OPTION:: @code{SET OPTION} syntax
+* GRANT:: @code{GRANT} and @code{REVOKE} syntax
+* CREATE INDEX:: @code{CREATE INDEX} syntax
+* DROP INDEX:: @code{DROP INDEX} syntax
+* Comments:: Comment syntax
+* CREATE FUNCTION:: @code{CREATE FUNCTION} syntax
+* Reserved words:: Is @strong{MySQL} picky about reserved words?
+
+Literals: how to write strings and numbers
+
+* String syntax:: Strings
+* Number syntax:: Numbers
+* Hexadecimal values:: Hexadecimal values
+* NULL values:: @code{NULL} values
+* Legal names:: Database, table, index, column and alias names
+
+Database, table, index, column and alias names
+
+* Name case sensitivity:: Case sensitivity in names
+
+Column types
+
+* Storage requirements:: Column type storage requirements
+* Numeric types:: Numeric types
+* Date and time types:: Date and time types
+* String types:: String types
+* Choosing types:: Choosing the right type for a column
+* Indexes:: Column indexes
+* Multiple-column indexes:: Multiple-column indexes
+* Other-vendor column types:: Using column types from other database engines
+
+Date and time types
+
+* Y2K issues:: Y2K issues and date types
+* DATETIME:: The @code{DATETIME}, @code{DATE} and @code{TIMESTAMP} types
+* TIME:: The @code{TIME} type
+* YEAR:: The @code{YEAR} type
+
+String types
+
+* CHAR:: The @code{CHAR} and @code{VARCHAR} types
+* BLOB:: The @code{BLOB} and @code{TEXT} types
+* ENUM:: The @code{ENUM} type
+* SET:: The @code{SET} type
+
+Functions for use in @code{SELECT} and @code{WHERE} clauses
+
+* Grouping functions:: Grouping functions
+* Arithmetic functions:: Normal arithmetic operations
+* Bit functions:: Bit functions
+* Logical functions:: Logical operations
+* Comparison functions:: Comparison operators
+* String comparison functions:: String comparison functions
+* Casts:: Cast operators
+* Control flow functions:: Control flow functions
+* Mathematical functions:: Mathematical functions
+* String functions:: String functions
+* Date and time functions:: Date and time functions
+* Miscellaneous functions:: Miscellaneous functions
+* Group by functions:: Functions for @code{GROUP BY} clause
+
+@code{CREATE TABLE} syntax
+
+* Silent column changes:: Silent column changes
+
+@code{SHOW} syntax (Get information about tables, columns,...)
+
+* SHOW DATABASE INFO::
+* SHOW TABLE STATUS::
+* SHOW STATUS::
+* SHOW VARIABLES::
+* SHOW PROCESSLIST::
+* SHOW GRANTS::
+
+MySQL table types
+
+* MyISAM:: MyISAM tables
+* ISAM:: ISAM tables
+* HEAP:: HEAP tables
+* BDB:: BDB or Berkeley_db tables
+
+MyISAM tables
+
+* Key space:: Space needed for keys
+* MyISAM table formats:: MyISAM table formats
+
+MyISAM table formats
+
+* Static format:: Static (Fixed-length) table characteristics
+* Dynamic format:: Dynamic table characteristics
+* Compressed format:: Compressed table characteristics
+
+MySQL Tutorial
+
+* Connecting-disconnecting:: Connecting to and disconnecting from the server
+* Entering queries:: Entering queries
+* Examples:: Examples
+* Searching on two keys:: Searching on two keys
+* Database use:: Creating and using a database
+* Getting information:: Getting information about databases and tables
+* Batch mode:: Using @code{mysql} in batch mode
+* Twin:: Queries from twin project
+
+Examples of common queries
+
+* example-Maximum-column:: The maximum value for a column
+* example-Maximum-row:: The row holding the maximum of a certain column
+* example-Maximum-column-group:: Maximum of column: per group: only the values
+* example-Maximum-column-group-row:: The rows holding the group-wise maximum of a certain field
+* example-Foreign keys:: Using foreign keys
+
+Creating and using a database
+
+* Creating database:: Creating a database
+* Creating tables:: Creating a table
+* Loading tables:: Loading data into a table
+* Retrieving data:: Retrieving information from a table
+* Multiple tables:: Using more than one table
+
+Retrieving information from a table
+
+* Selecting all:: Selecting all data
+* Selecting rows:: Selecting particular rows
+* Selecting columns:: Selecting particular columns
+* Sorting rows:: Sorting rows
+* Date calculations:: Date calculations
+* Working with NULL:: Working with @code{NULL} values
+* Pattern matching:: Pattern matching
+* Counting rows:: Counting rows
+
+Queries from twin project
+
+* Twin pool:: Find all non-distributed twins
+* Twin event:: Show a table on twin pair status
+
+MySQL server functions
+
+* Languages:: What languages are supported by @strong{MySQL}?
+* Table size:: How big @strong{MySQL} tables can be
+
+What languages are supported by MySQL?
+
+* Character sets:: The character set used for data and sorting
+* Adding character set:: Adding a new character set
+* String collating:: String collating support
+* Multi-byte characters:: Multi-byte character support
+
+Replication in MySQL
+
+* Replication Intro:: Introduction
+* Replication Implementation:: Replication Implementation Overview
+* Replication HOWTO:: HOWTO
+* Replication Features:: Replication Features
+* Replication Options:: Replication Options in my.cnf
+* Replication SQL:: SQL Commands related to replication
+
+Getting maximum performance from MySQL
+
+* Optimize Basics:: Optimization overview
+* System:: System/Compile time and startup parameter tuning
+* Data size:: Get your data as small as possible
+* MySQL indexes:: How @strong{MySQL} uses indexes
+* Query Speed:: Speed of queries that access or update data
+* Tips:: Other optimization tips
+* Benchmarks:: Using your own benchmarks
+* Design:: Design choices
+* Design Limitations:: MySQL design limitations/tradeoffs
+* Portability:: Portability
+* Internal use:: What have we used MySQL for?
+
+System/Compile time and startup parameter tuning
+
+* Compile and link options:: How compiling and linking affects the speed of MySQL
+* Disk issues:: Disk issues
+* Server parameters:: Tuning server parameters
+* Table cache:: How MySQL opens and closes tables
+* Creating many tables:: Drawbacks of creating large numbers of tables in the same database
+* Open tables:: Why so many open tables?
+* Memory use:: How MySQL uses memory
+* Internal locking:: How MySQL locks tables
+* Table locking:: Table locking issues
+
+Disk issues
+
+* Symbolic links:: Using symbolic links for databases and tables
+
+Speed of queries that access or update data
+
+* Estimating performance:: Estimating query performance
+* SELECT speed:: Speed of @code{SELECT} queries
+* Where optimizations:: How MySQL optimizes @code{WHERE} clauses
+* LEFT JOIN optimization:: How MySQL optimizes @code{LEFT JOIN}
+* LIMIT optimization:: How MySQL optimizes @code{LIMIT}
+* Insert speed:: Speed of @code{INSERT} queries
+* Update speed:: Speed of @code{UPDATE} queries
+* Delete speed:: Speed of @code{DELETE} queries
+
+MySQL Utilites
+
+* Programs:: What do the executables do?
+* mysql:: The command line tool
+* mysqladmin:: Administering a @strong{MySQL} server
+* mysqldump:: Dumping the structure and data from @strong{MySQL} databases and tables
+* mysqlimport:: Importing data from text files
+* mysqlshow:: Showing databases, tables and columns
+* myisampack:: The @strong{MySQL} compressed read-only table generator
+
+Maintaining a MySQL installation
+
+* Table maintenance:: Table maintenance and crash recovery
+* Maintenance regimen:: Setting up a table maintenance regimen
+* Table-info:: Getting information about a table
+* Crash recovery:: Using @code{myisamchk} for crash recovery
+* Log files:: Log file maintenance
+
+Using @code{myisamchk} for table maintenance and crash recovery
+
+* myisamchk syntax:: @code{myisamchk} invocation syntax
+* myisamchk memory:: @code{myisamchk} memory usage
+
+@code{myisamchk} invocation syntax
+
+* myisamchk general options::
+* myisamchk check options::
+* myisamchk repair options::
+* myisamchk other options::
+
+Using @code{myisamchk} for crash recovery
+
+* Check:: How to check tables for errors
+* Repair:: How to repair tables
+* Optimization:: Table optimization
+
+Adding new functions to MySQL
+
+* Adding UDF:: Adding a new user-definable function
+* Adding native function:: Adding a new native function
+
+Adding a new user-definable function
+
+* UDF calling sequences:: UDF calling sequences
+* UDF arguments:: Argument processing
+* UDF return values:: Return values and error handling
+* UDF compiling:: Compiling and installing user-definable functions
+
+Adding new procedures to MySQL
+
+* procedure analyse:: Procedure analyse
+* Writing a procedure:: Writing a procedure.
+
+MySQL ODBC Support
+
+* Which ODBC OS:: Operating systems supported by @strong{MyODBC}
+* ODBC administrator:: How to fill in the various fields in the ODBC administrator program
+* ODBC Problems:: How to report problems with @strong{MySQL} ODBC
+* MyODBC clients:: Programs known to work with @strong{MyODBC}
+* ODBC and last_insert_id:: How to get the value of an @code{AUTO_INCREMENT} column in ODBC
+* MyODBC bug report:: Reporting problems with MyODBC
+
+Using @code{MySQL} with some common programs
+
+* Apache:: Using @strong{MySQL} with Apache
+
+Problems and common errors
+
+* What is crashing:: How to determinate what is causing problems
+* Crashing:: What to do if @strong{MySQL} keeps crashing
+* Link errors:: Problems when linking with the @strong{MySQL} client library
+* Common errors:: Some common errors when using @strong{MySQL}
+* Full disk:: How @strong{MySQL} handles a full disk
+* Multiple sql commands:: How to run SQL commands from a text file
+* Temporary files:: Where @strong{MySQL} stores temporary files
+* Problems with mysql.sock:: How to protect @file{/tmp/mysql.sock}
+* Error Access denied:: @code{Access denied} error
+* Changing MySQL user :: How to run @strong{MySQL} as a normal user
+* Resetting permissions:: How to reset a forgotten password.
+* File permissions :: Problems with file permissions
+* Not enough file handles:: File not found
+* Using DATE:: Problems using @code{DATE} columns
+* Timezone problems:: Timezone problems
+* Case sensitivity:: Case sensitivity in searches
+* Problems with NULL:: Problems with @code{NULL} values
+* Problems with alias:: Problems with @code{alias}
+* Deleting from related tables:: Deleting rows from related tables
+* No matching rows:: Solving problems with no matching rows
+* ALTER TABLE problems:: Problems with @code{ALTER TABLE}.
+* Change column order:: How to change the order of columns in a table
+
+Some common errors when using MySQL
+
+* Gone away:: @code{MySQL server has gone away} error
+* Can not connect to server:: @code{Can't connect to [local] MySQL server} error
+* Blocked host:: @code{Host '...' is blocked} error
+* Too many connections:: @code{Too many connections} error
+* Out of memory:: @code{Out of memory} error
+* Packet too large:: @code{Packet too large} error
+* Communication errors::
+* Full table:: @code{The table is full} error
+* Commands out of sync:: @code{Commands out of sync} error in client
+* Ignoring user:: @code{Ignoring user} error
+* Cannot find table:: @code{Table 'xxx' doesn't exist} error
+
+Solving some common problems with MySQL
+
+* Log Replication:: Database replication with update log
+* Backup:: Database backups
+* Update log:: The update log
+* Multiple servers:: Running multiple @strong{MySQL} servers on the same machine
+
+MySQL client tools and APIs
+
+* C:: @strong{MySQL} C API
+* C API datatypes:: C API datatypes
+* C API function overview:: C API function Overview
+* C API functions:: C API function descriptions
+* Perl:: @strong{MySQL} Perl API
+* Eiffel:: @strong{MySQL} Eiffel wrapper
+* Java:: @strong{MySQL} Java connectivity (JDBC)
+* PHP:: @strong{MySQL} PHP API
+* Cplusplus:: @strong{MySQL} C++ APIs
+* Python:: @strong{MySQL} Python APIs
+* Tcl:: @strong{MySQL} Tcl APIs
+
+C API function descriptions
+
+* mysql_affected_rows:: @code{mysql_affected_rows()}
+* mysql_close:: @code{mysql_close()}
+* mysql_connect:: @code{mysql_connect()}
+* mysql_change_user:: @code{mysql_change_user()}
+* mysql_character_set_name:: @code{mysql_character_set_name()}
+* mysql_create_db:: @code{mysql_create_db()}
+* mysql_data_seek:: @code{mysql_data_seek()}
+* mysql_debug:: @code{mysql_debug()}
+* mysql_drop_db:: @code{mysql_drop_db()}
+* mysql_dump_debug_info:: @code{mysql_dump_debug_info()}
+* mysql_eof:: @code{mysql_eof()}
+* mysql_errno:: @code{mysql_errno()}
+* mysql_error:: @code{mysql_error()}
+* mysql_escape_string:: @code{mysql_escape_string()}
+* mysql_fetch_field:: @code{mysql_fetch_field()}
+* mysql_fetch_fields:: @code{mysql_fetch_fields()}
+* mysql_fetch_field_direct:: @code{mysql_fetch_field_direct()}
+* mysql_fetch_lengths:: @code{mysql_fetch_lengths()}
+* mysql_fetch_row:: @code{mysql_fetch_row()}
+* mysql_field_count:: @code{mysql_field_count()}
+* mysql_field_seek:: @code{mysql_field_seek()}
+* mysql_field_tell:: @code{mysql_field_tell()}
+* mysql_free_result:: @code{mysql_free_result()}
+* mysql_get_client_info:: @code{mysql_get_client_info()}
+* mysql_get_host_info:: @code{mysql_get_host_info()}
+* mysql_get_proto_info:: @code{mysql_get_proto_info()}
+* mysql_get_server_info:: @code{mysql_get_server_info()}
+* mysql_info:: @code{mysql_info()}
+* mysql_init:: @code{mysql_init()}
+* mysql_insert_id:: @code{mysql_insert_id()}
+* mysql_kill:: @code{mysql_kill()}
+* mysql_list_dbs:: @code{mysql_list_dbs()}
+* mysql_list_fields:: @code{mysql_list_fields()}
+* mysql_list_processes:: @code{mysql_list_processes()}
+* mysql_list_tables:: @code{mysql_list_tables()}
+* mysql_num_fields:: @code{mysql_num_fields()}
+* mysql_num_rows:: @code{mysql_num_rows()}
+* mysql_options:: @code{mysql_options()}
+* mysql_ping:: @code{mysql_ping()}
+* mysql_query:: @code{mysql_query()}
+* mysql_real_connect:: @code{mysql_real_connect()}
+* mysql_real_escape_string:: @code{mysql_real_escape_string()}
+* mysql_real_query:: @code{mysql_real_query()}
+* mysql_reload:: @code{mysql_reload()}
+* mysql_row_seek:: @code{mysql_row_seek()}
+* mysql_row_tell:: @code{mysql_row_tell()}
+* mysql_select_db:: @code{mysql_select_db()}
+* mysql_shutdown:: @code{mysql_shutdown()}
+* mysql_stat:: @code{mysql_stat()}
+* mysql_store_result:: @code{mysql_store_result()}
+* mysql_thread_id:: @code{mysql_thread_id()}
+* mysql_use_result:: @code{mysql_use_result()}
+* NULL mysql_store_result:: Why is it that after @code{mysql_query()} returns success, @code{mysql_store_result()} sometimes returns @code{NULL?}
+* Query results:: What results can I get from a query?
+* Getting unique ID:: How can I get the unique ID for the last inserted row?
+* C API linking problems:: Problems linking with the C API
+* Thread-safe clients:: How to make a thread-safe client
+
+MySQL Perl API
+
+* DBI with DBD:: @code{DBI} with @code{DBD::mysql}
+* Perl DBI Class:: The @code{DBI} interface
+* DBI-info:: More @code{DBI}/@code{DBD} information
+
+MySQL PHP API
+
+* PHP problems:: Common problems with MySQL and PHP
+
+How MySQL compares to other databases
+
+* Compare mSQL:: How @strong{MySQL} compares to @code{mSQL}
+* Compare PostgreSQL:: How @strong{MySQL} compares with PostgreSQL
+
+How MySQL compares to @code{mSQL}
+
+* Using mSQL tools:: How to convert @code{mSQL} tools for @strong{MySQL}
+* Protocol differences:: How @code{mSQL} and @strong{MySQL} client/server communications protocols differ
+* Syntax differences:: How @code{mSQL} 2.0 SQL syntax differs from @strong{MySQL}
+
+MySQL internals
+
+* MySQL threads:: MySQL threads
+
+MySQL change history
+
+* News-3.23.x:: Changes in release 3.23.x (Released as alpha)
+* News-3.22.x:: Changes in release 3.22.x (Recommended version)
+* News-3.21.x:: Changes in release 3.21.x
+* News-3.20.x:: Changes in release 3.20.x
+* News-3.19.x:: Changes in release 3.19.x
+
+Changes in release 3.23.x (Released as alpha)
+
+* News-3.23.22:: Changes in release 3.23.22
+* News-3.23.21:: Changes in release 3.23.21
+* News-3.23.20:: Changes in release 3.23.20
+* News-3.23.19:: Changes in release 3.23.19
+* News-3.23.18:: Changes in release 3.23.18
+* News-3.23.17:: Changes in release 3.23.17
+* News-3.23.16:: Changes in release 3.23.16
+* News-3.23.15:: Changes in release 3.23.15
+* News-3.23.14:: Changes in release 3.23.14
+* News-3.23.13:: Changes in release 3.23.13
+* News-3.23.12:: Changes in release 3.23.12
+* News-3.23.11:: Changes in release 3.23.11
+* News-3.23.10:: Changes in release 3.23.10
+* News-3.23.9:: Changes in release 3.23.9
+* News-3.23.8:: Changes in release 3.23.8
+* News-3.23.7:: Changes in release 3.23.7
+* News-3.23.6:: Changes in release 3.23.6
+* News-3.23.5:: Changes in release 3.23.5
+* News-3.23.4:: Changes in release 3.23.4
+* News-3.23.3:: Changes in release 3.23.3
+* News-3.23.2:: Changes in release 3.23.2
+* News-3.23.1:: Changes in release 3.23.1
+* News-3.23.0:: Changes in release 3.23.0
+
+Changes in release 3.22.x
+
+* News-3.22.35:: Changes in release 3.22.35
+* News-3.22.34:: Changes in release 3.22.34
+* News-3.22.33:: Changes in release 3.22.33
+* News-3.22.32:: Changes in release 3.22.32
+* News-3.22.31:: Changes in release 3.22.31
+* News-3.22.30:: Changes in release 3.22.30
+* News-3.22.29:: Changes in release 3.22.29
+* News-3.22.28:: Changes in release 3.22.28
+* News-3.22.27:: Changes in release 3.22.27
+* News-3.22.26:: Changes in release 3.22.26
+* News-3.22.25:: Changes in release 3.22.25
+* News-3.22.24:: Changes in release 3.22.24
+* News-3.22.23:: Changes in release 3.22.23
+* News-3.22.22:: Changes in release 3.22.22
+* News-3.22.21:: Changes in release 3.22.21
+* News-3.22.20:: Changes in release 3.22.20
+* News-3.22.19:: Changes in release 3.22.19
+* News-3.22.18:: Changes in release 3.22.18
+* News-3.22.17:: Changes in release 3.22.17
+* News-3.22.16:: Changes in release 3.22.16
+* News-3.22.15:: Changes in release 3.22.15
+* News-3.22.14:: Changes in release 3.22.14
+* News-3.22.13:: Changes in release 3.22.13
+* News-3.22.12:: Changes in release 3.22.12
+* News-3.22.11:: Changes in release 3.22.11
+* News-3.22.10:: Changes in release 3.22.10
+* News-3.22.9:: Changes in release 3.22.9
+* News-3.22.8:: Changes in release 3.22.8
+* News-3.22.7:: Changes in release 3.22.7
+* News-3.22.6:: Changes in release 3.22.6
+* News-3.22.5:: Changes in release 3.22.5
+* News-3.22.4:: Changes in release 3.22.4
+* News-3.22.3:: Changes in release 3.22.3
+* News-3.22.2:: Changes in release 3.22.2
+* News-3.22.1:: Changes in release 3.22.1
+* News-3.22.0:: Changes in release 3.22.0
+
+Changes in release 3.21.x
+
+* News-3.21.33:: Changes in release 3.21.33
+* News-3.21.32:: Changes in release 3.21.32
+* News-3.21.31:: Changes in release 3.21.31
+* News-3.21.30:: Changes in release 3.21.30
+* News-3.21.29:: Changes in release 3.21.29
+* News-3.21.28:: Changes in release 3.21.28
+* News-3.21.27:: Changes in release 3.21.27
+* News-3.21.26:: Changes in release 3.21.26
+* News-3.21.25:: Changes in release 3.21.25
+* News-3.21.24:: Changes in release 3.21.24
+* News-3.21.23:: Changes in release 3.21.23
+* News-3.21.22:: Changes in release 3.21.22
+* News-3.21.21a:: Changes in release 3.21.21a
+* News-3.21.21:: Changes in release 3.21.21
+* News-3.21.20:: Changes in release 3.21.20
+* News-3.21.19:: Changes in release 3.21.19
+* News-3.21.18:: Changes in release 3.21.18
+* News-3.21.17:: Changes in release 3.21.17
+* News-3.21.16:: Changes in release 3.21.16
+* News-3.21.15:: Changes in release 3.21.15
+* News-3.21.14b:: Changes in release 3.21.14b
+* News-3.21.14a:: Changes in release 3.21.14a
+* News-3.21.13:: Changes in release 3.21.13
+* News-3.21.12:: Changes in release 3.21.12
+* News-3.21.11:: Changes in release 3.21.11
+* News-3.21.10:: Changes in release 3.21.10
+* News-3.21.9:: Changes in release 3.21.9
+* News-3.21.8:: Changes in release 3.21.8
+* News-3.21.7:: Changes in release 3.21.7
+* News-3.21.6:: Changes in release 3.21.6
+* News-3.21.5:: Changes in release 3.21.5
+* News-3.21.4:: Changes in release 3.21.4
+* News-3.21.3:: Changes in release 3.21.3
+* News-3.21.2:: Changes in release 3.21.2
+* News-3.21.0:: Changes in release 3.21.0
+
+Changes in release 3.20.x
+
+* News-3.20.18:: Changes in release 3.20.18
+* News-3.20.17:: Changes in release 3.20.17
+* News-3.20.16:: Changes in release 3.20.16
+* News-3.20.15:: Changes in release 3.20.15
+* News-3.20.14:: Changes in release 3.20.14
+* News-3.20.13:: Changes in release 3.20.13
+* News-3.20.11:: Changes in release 3.20.11
+* News-3.20.10:: Changes in release 3.20.10
+* News-3.20.9:: Changes in release 3.20.9
+* News-3.20.8:: Changes in release 3.20.8
+* News-3.20.7:: Changes in release 3.20.7
+* News-3.20.6:: Changes in release 3.20.6
+* News-3.20.3:: Changes in release 3.20.3
+* News-3.20.0:: Changes in releases 3.20.0
+
+Changes in release 3.19.x
+
+* News-3.19.5:: Changes in release 3.19.5
+* News-3.19.4:: Changes in release 3.19.4
+* News-3.19.3:: Changes in release 3.19.3
+
+List of things we want to add to MySQL in the future (The TODO)
+
+* TODO future:: Things that must done in the very near future
+* TODO sometime:: Things that have to be done sometime
+* TODO unplanned:: Some things we don't have any plans to do
+
+Comments on porting to other systems
+
+* Debugging server:: Debugging a @strong{MySQL} server
+* Debugging client:: Debugging a @strong{MySQL} client
+* The DBUG package:: The DBUG package
+* Locking methods::
+* RTS-threads:: Comments about RTS threads
+* Thread packages:: Differences between different thread packages
+
+@end detailmenu
+@end menu
+
+@cindex Overview
+@cindex General Information
+@node Introduction, Questions, Top, Top
+@chapter General Information about MySQL
+
+@menu
+* What-is:: What is @strong{MySQL}?
+* Manual-info:: About this manual
+* History:: History of @strong{MySQL}
+* MySQL-Books:: Books about MySQL
+* Features:: The main features of @strong{MySQL}
+* Stability:: How stable is @strong{MySQL}?
+* Year 2000 compliance:: Year 2000 compliance
+* General-SQL:: General SQL information and tutorials
+* Useful Links:: Useful @strong{MySQL}-related links
+@end menu
+
+This is the @strong{MySQL} reference manual; it documents @strong{MySQL}
+version @value{mysql_version}. As @strong{MySQL} is work in progress,
+the manual gets updated frequently. So there is a very good chance that
+this version is out of date, unless you are looking at it on-line. The
+most recent version of this manual is available at
+@uref{http://www.mysql.com/documentation/} in many different formats. If you
+have a hard time finding the information in the manual, you can try its
+searchable PHP version at @uref{http://www.mysql.com/documentation/manual.php} .
+
+@strong{MySQL} is a very fast, multi-threaded, multi-user and robust SQL
+(Structured Query Language) database server.
+
+@strong{MySQL} is free software. It is licensed with the @strong{GNU
+GENERAL PUBLIC LICENSE} @uref{http://www.gnu.org/}. @xref{Licensing and
+Support}.
+
+@uref{http://www.mysql.com/, The @strong{MySQL} home page}
+provides the latest information about @strong{MySQL}.
+
+The following list describes some useful sections of the manual:
+
+@itemize @bullet
+@item
+For a discussion of @strong{MySQL}'s capabilities, see @ref{Features}.
+
+@item
+For installation instructions, see @ref{Installing}. For tips on porting
+@strong{MySQL} to new machines or operating systems, see @ref{Porting}.
+
+@item
+For information about upgrading from a 3.21 release, see
+@ref{Upgrading-from-3.21}.
+
+@item
+For a tutorial introduction to @strong{MySQL}, see
+@ref{Tutorial}.
+
+@item
+For examples of SQL and benchmarking information, see the benchmarking
+directory (@file{sql-bench} in the distribution).
+
+@item
+For a history of new features and bug fixes, see @ref{News}.
+
+@item
+For a list of currently known bugs and misfeatures, see @ref{Bugs}.
+
+@item
+For future plans, see @ref{TODO}.
+
+@item
+For a list of all the contributors to this project, see @ref{Credits}.
+@end itemize
+
+@strong{IMPORTANT:}
+
+@c if the @email is at the beginning of a line the texi2html fails
+Reports of errors (often called bugs), as well as questions and comments
+should be sent to the mailing list at @email{mysql@@lists.mysql.com}.
+@xref{Bug reports}.
+The @code{mysqlbug} script should be used to generate bug reports.
+@c FIX! RPMs are also binary
+For source distributions, the @code{mysqlbug} script can be found in the
+@file{scripts} directory. For binary distributions, @code{mysqlbug} can
+be found in the @file{bin} directory.
+
+@c FIX! Remeber to create the alias!
+If you have any suggestions concerning additions or corrections to this
+manual, please send them to the manual team at
+(@email{docs@@mysql.com}).
+
+This is a reference manual; it does not provide general instruction on SQL
+or relational database concepts. If you want general information about SQL,
+see @ref{General-SQL}. For books that focus more specifically on
+@strong{MySQL}, see @ref{MySQL-Books}.
+
+@cindex @strong{MySQL}, what it is
+@node What-is, Manual-info, Introduction, Introduction
+@section What is MySQL
+
+@table @asis
+
+@item @strong{MySQL} is a database management system.
+
+A database is a structured collection of data. It may be anything from a
+simple shopping list to a picture gallery or the vast amounts of
+information in a corporate network. To add, access and process data
+stored in a computer database, you need a database management system
+such as @strong{MySQL}. Since computers are very good at handling large
+amounts of data, database management plays a central role in computing,
+as stand-alone utilities or as parts of other applications.
+
+@item @strong{MySQL} is a relational database management system.
+
+A relational database stores data in separate tables rather than putting
+all the data in one big storeroom. This adds speed and flexibility. The
+tables are linked by defined relations making it possible to combine
+data from several tables on request. The SQL part of @strong{MySQL}
+stands for "Structured Query Language" - the most common standardized
+language used to access databases.
+
+@item @strong{MySQL} is Open Source Software
+
+Open source means that it is possible to use and modify for
+anyone. Anybody can download @strong{MySQL} from the Internet and use it
+without paying anything. Anybody so inclined can study the source code
+and change it to fit their needs. @strong{MySQL} uses the GPL (GNU
+General Public License) @uref{http://www.gnu.org}, to define what You
+may and may not do with the software in different situations. If you
+feel uncomfortable with the GPL or need to embed @strong{MySQL} into a
+commercial application you can buy a commercially licensed version from
+us.
+
+@item Why use @strong{MySQL}?
+
+@strong{MySQL} is very fast, reliable and easy to use. If that is what
+You are looking for you should give it a try. @strong{MySQL} also has a
+very practical set of features developed in very close cooperation with
+our users. You can find a performance comparison of @strong{MySQL}
+to some other database managers on our benchmark page. @xref{Benchmarks}.
+
+@strong{MySQL} was originally developed to handle very large databases
+much faster than existing solutions and has been successfully used in
+highly demanding production environments for several years. Though
+under constant development, @strong{MySQL} today offers a rich and very
+useful set of functions. The connectivity, speed and security makes
+@strong{MySQL} highly suited for accessing databases on the Internet.
+
+@item The technical features of @strong{MySQL}
+
+For advanced technical information, @ref{Reference}. @strong{MySQL} is
+a client/server system that consists of an multi-threaded SQL server
+that supports different backends, several different client programs and
+libraries, administrative tools and a programming interface.
+
+@item @strong{MySQL} has a lot of contributed software available.
+
+This makes it much more likely that you will find that your favorite
+application/language already supports @strong{MySQL}.
+
+@end table
+
+@cindex How to pronounce @strong{MySQL}
+@cindex @strong{MySQL}, how to pronounce
+The official way to pronounce @strong{MySQL} is ``My Ess Que Ell'' (not
+MY-SEQUEL). But we try to avoid correcting people who say MY-SEQUEL
+
+@strong{MySQL} core values
+
+We want @strong{MySQL} to be
+
+@itemize @bullet
+@item
+The best and the most used database in the world
+@item
+Available to all and affordable for all
+@item
+Easy to use
+@item
+Continuously improved while remaining fast and safe
+@item
+Fun to use and fun to improve
+@item
+Free from bugs
+@end itemize
+
+@strong{MySQL AB} and the people of @strong{MySQL AB}
+
+@itemize @bullet
+@item
+Promote Open Source Philosophy and support the Open Source Community
+@item
+Aims to be good citizens
+@item
+Prefer partners that share our values and mind-set
+@item
+Answer mail and give support
+@item
+Is a virtual company networking with others
+@item
+Work against software patents
+@end itemize
+
+@cindex Manual information
+@node Manual-info, History, What-is, Introduction
+@section About this manual
+
+@menu
+* Manual conventions:: Conventions used in this manual
+@end menu
+
+This manual is currently available in Texinfo, plain text, Info, HTML,
+PostScript and PDF versions. Because of their size, PostScript and PDF
+versions are not included with the main @strong{MySQL} distribution, but
+are available for separate download at
+@uref{http://www.mysql.com/}.
+
+The primary document is the Texinfo file. The HTML version is produced
+automatically using a modified version of @code{texi2html}. The plain
+text and Info versions are produced with @code{makeinfo}. The Postscript
+version is produced using @code{texi2dvi} and @code{dvips}. The PDF
+version is produced with @code{pdftex}.
+
+This manual is written and maintained by David Axmark, Michael (Monty)
+Widenius and Paul DuBois. For other contributors, see @ref{Credits}.
+
+@node Manual conventions, , Manual-info, Manual-info
+@subsection Conventions used in this manual
+
+This manual uses certain typographical conventions:
+
+@table @asis
+@item @code{constant}
+Constant-width font is used for command names and options; SQL statements;
+database, table and column names; C and Perl code; and environment variables.
+Example: ``To see how @code{mysqladmin} works, invoke it with the
+@code{--help} option.''
+
+@item @file{filename}
+Constant-width font with surrounding quotes is used for filenames and
+pathnames. Example: ``The distribution is installed under the
+@file{/usr/local/} directory.''
+
+@item @samp{c}
+Constant-width font with surrounding quotes is also used to indicate
+character sequences. Example: ``To specify a wildcard, use the @samp{%}
+character.''
+
+@item @emph{italic}
+Italic font is used for emphasis, @emph{like this}.
+
+@item @strong{boldface}
+Boldface font is used for access privilege names (e.g., ``do not grant the
+@strong{process} privilege lightly'') and occasionally to convey
+@strong{especially strong emphasis}.
+@end table
+
+When commands are shown that are meant to be executed by a particular
+program, the program is indicated by the prompt shown with the command. For
+example, @code{shell>} indicates a command that you execute from your login
+shell, and @code{mysql>} indicates a command that you execute from the
+@code{mysql} client program:
+
+@example
+shell> type a shell command here
+mysql> type a mysql command here
+@end example
+
+Shell commands are shown using Bourne shell syntax. If you are using a
+@code{csh}-style shell, you may need to issue commands slightly differently.
+For example, the sequence to set an environment variable and run a command
+looks like this in Bourne shell syntax:
+
+@example
+shell> VARNAME=value some_command
+@end example
+
+For @code{csh}, you would execute the sequence like this:
+
+@example
+shell> setenv VARNAME value
+shell> some_command
+@end example
+
+Database, table and column names often must be substituted into commands. To
+indicate that such substitution is necessary, this manual uses
+@code{db_name}, @code{tbl_name} and @code{col_name}. For example, you might
+see a statement like this:
+
+@example
+mysql> SELECT col_name FROM db_name.tbl_name;
+@end example
+
+This means that if you were to enter a similar statement, you would supply
+your own database, table and column names, perhaps like this:
+
+@example
+mysql> SELECT author_name FROM biblio_db.author_list;
+@end example
+
+SQL statements may be written in uppercase or lowercase. When this manual
+shows a SQL statement, uppercase is used for particular keywords if those
+keywords are under discussion (to emphasize them) and lowercase is used for
+the rest of the statement. For example, you might see the following in a
+discussion of the @code{SELECT} statement:
+
+@example
+mysql> SELECT count(*) FROM tbl_name;
+@end example
+
+On the other hand, in a discussion of the @code{COUNT()} function, the
+same statement would be written like this:
+
+@example
+mysql> select COUNT(*) from tbl_name;
+@end example
+
+If no particular emphasis is intended, all keywords are written uniformly
+in uppercase.
+
+In syntax descriptions, square brackets (@samp{[} and @samp{]}) are used
+to indicate optional words or clauses:
+
+@example
+DROP TABLE [IF EXISTS] tbl_name
+@end example
+
+When a syntax element consists of a number of alternatives, the alternatives
+are separated by vertical bars (@samp{|}). When one member from a set of
+choices may be chosen, the alternatives are listed within square brackets
+(@samp{[} and @samp{]}):
+
+@example
+TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)
+@end example
+
+When one member from a set of choices must be chosen, the alternatives are
+listed within braces (@samp{@{} and @samp{@}}):
+
+@example
+@{DESCRIBE | DESC@} tbl_name @{col_name | wild@}
+@end example
+
+@cindex @strong{MySQL} version
+@node History, MySQL-Books, Manual-info, Introduction
+@section History of MySQL
+
+We once started out with the intention of using @code{mSQL} to connect to our
+tables using our own fast low-level (ISAM) routines. However, after some
+testing we came to the conclusion that @code{mSQL} was not fast enough or
+flexible enough for our needs. This resulted in a new SQL interface to our
+database but with almost the same API interface as @code{mSQL}. This API was
+chosen to ease porting of third-party code.
+
+The derivation of the name @strong{MySQL} is not perfectly clear. Our base
+directory and a large number 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 @strong{MySQL} is
+still a mystery, even for us.
+
+@node MySQL-Books, Features, History, Introduction
+@section Books about MySQL
+
+While this manual is still the right place for up to date techical
+information, its primary goal is to contain everything there is to know
+about @strong{MySQL}. And it is sometimes nice to have a bound book to read
+in bed or while you travel. Here is a list of books about @strong{MySQL} (in
+English).
+
+@multitable @columnfractions .3 .7
+@item Title @tab @uref{http://www2.newriders.com/cfm/prod_book.cfm?RecordID=584,MySQL}
+@item Publisher @tab New Riders
+@item Author @tab Paul DuBois
+@item Pub Date @tab 1st Edition December 1999
+@item ISBN @tab 0735709211
+@item Pages @tab 800
+@item Price @tab $49.99 US
+@item Downloadable examples @tab @uref{http://www.mysql.com/Contrib/Examples/samp_db.tar.gz, @code{samp_db.tar.gz}}
+@item Errata @tab @uref{http://www.mysql.com/documentation/pauls-mysql-book-errata.html, are available here}
+@end multitable
+Foreword by Michael ``Monty'' Widenius, @strong{MySQL} Moderator
+
+In @strong{MySQL}, Paul DuBois provides you with a comprehensive guide to
+one of the most popular relational database systems. Paul has
+contributed to the online documentation for @strong{MySQL}, and is an
+active member of the @strong{MySQL} community. The principal @strong{MySQL}
+developer, Monty Widenius, and a network of his fellow developers
+reviewed the manuscript, providing Paul with the kind of insight
+no one else could supply.
+
+Instead of merely giving you a general overview of @strong{MySQL}, Paul
+teaches you how to make the most of its capabilities. Through two
+sample database applications that run throughout the book, he
+gives you solutions to problems you're sure to face. He helps you
+integrate @strong{MySQL} efficiently with third-party tools, such as PHP
+and Perl, enabling you to generate dynamic Web pages through
+database queries. He teaches you to write programs that access
+@strong{MySQL} databases, and also provides a comprehensive set of
+references to column types, operators, functions, SQL syntax,
+@strong{MySQL} programming, C API, Perl @code{DBI}, and PHP API.
+@strong{MySQL} simply gives you the kind of information you won't find
+anywhere else.
+
+If you use @strong{MySQL}, this book provides you with:
+@itemize @bullet
+@item
+An introduction to @strong{MySQL} and SQL
+@item
+Coverage of @strong{MySQL}'s data types and how to use them
+@item
+Thorough treatment of how to write client programs in C
+@item
+A guide to using the Perl @code{DBI} and PHP APIs for developing
+command-line and Web-based applications
+@item
+Tips on administrative issues such as user accounts, backup,
+crash recovery, and security
+@item
+Help in choosing an ISP for @strong{MySQL} access
+@item
+A comprehensive reference for @strong{MySQL}'s data types, operators,
+functions, and SQL statements and utilities
+@item
+Complete reference guides for @strong{MySQL}'s C API, the Perl @code{DBI} API,
+and PHP's @strong{MySQL}-related functions
+@end itemize
+
+@multitable @columnfractions .3 .7
+@item Title @tab @uref{http://www.oreilly.com/catalog/msql/noframes.html,MySQL & mSQL}
+@item Publisher @tab O'Reilly
+@item Authors @tab Randy Jay Yarger, George Reese & Tim King
+@item Pub Date @tab 1st Edition July 1999
+@item ISBN @tab 1-56592-434-7, Order Number: 4347
+@item Pages @tab 506
+@item Price @tab $34.95
+@end multitable
+
+This book teaches you how to use @strong{MySQL} and @code{mSQL}, two popular and
+robust database products that support key subsets of SQL on both Linux
+and UNIX systems. Anyone who knows basic C, Java, Perl, or Python can
+write a program to interact with a database, either as a stand-alone
+application or through a Web page. This book takes you through the
+whole process, from installation and configuration to programming
+interfaces and basic administration. Includes ample tutorial
+material.
+
+@multitable @columnfractions .3 .7
+@item Title @tab @uref{http://shop.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=0672319144,Sams Teach Yourself MySQL in 21 Days}
+@item Publisher @tab Sams
+@item Authors @tab Mark Maslakowski and Tony Butcher
+@item Pub Date @tab June 2000
+@item ISBN @tab 0672319144
+@item Pages @tab N/A
+@item Price @tab $39.99
+@end multitable
+
+Sams Teach Yourself @strong{MySQL} in 21 Days is for intermediate Linux users
+who want to move into databases. A large share of the audience to be web
+developers needing a database to store large amounts of information that can
+be retrieved via the Web. Sams Teach Yourself @strong{MySQL} in 21 Days is a
+practical, step-by-step tutorial. The reader will learn to design and employ
+this open source database technology into his/her web site using practical,
+hands-on examples to follow.
+
+@multitable @columnfractions .3 .7
+@item Title @tab @uref{http://shop.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=0761524452,E-Commerce Solutions with MySQL}
+@item Publisher @tab Prima
+@item Authors @tab N/A
+@item Pub Date @tab September 2000
+@item ISBN @tab 0761524452
+@item Pages @tab 500
+@item Price @tab $39.99
+@end multitable
+
+No description available.
+
+@multitable @columnfractions .3 .7
+@item Title @tab @uref{http://shop.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=1861004281,Professional MySQL Programming}
+@item Publisher @tab Wrox
+@item Authors @tab N/A
+@item Pub Date @tab July 2000
+@item ISBN @tab 1861004281
+@item Pages @tab 1000
+@item Price @tab $49.99
+@end multitable
+
+No description available.
+
+@multitable @columnfractions .3 .7
+@item Title @tab @uref{http://shop.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=0672317842,PHP3 and MySQL Web Development}
+@item Publisher @tab N/A
+@item Authors @tab William Jason Gilmore
+@item Pub Date @tab October 2000
+@item ISBN @tab 672317842
+@item Pages @tab N/A
+@item Price @tab $39.99
+@end multitable
+
+No description available.
+
+@node Features, Stability, MySQL-Books, Introduction
+@section The main features of MySQL
+
+The following list describes some of the important characteristics
+of @strong{MySQL}:
+
+@c This list is too technical and should be divided into one feature
+@c list comparable to commercial competition and a very technical on
+@c with max limits (from crash-me) and so on.
+@itemize @bullet
+@item
+Fully multi-threaded using kernel threads. That means it easily can
+use multiple CPUs if available.
+
+@item
+C, C++, Eiffel, Java, Perl, PHP, Python and Tcl APIs. @xref{Clients}.
+
+@item
+Works on many different platforms. @xref{Which OS}.
+
+@item
+Many column types: signed/unsigned integers 1, 2, 3, 4 and 8 bytes
+long, @code{FLOAT}, @code{DOUBLE}, @code{CHAR}, @code{VARCHAR},
+@code{TEXT}, @code{BLOB}, @code{DATE}, @code{TIME}, @code{DATETIME},
+@code{TIMESTAMP}, @code{YEAR}, @code{SET} and @code{ENUM} types. @xref{Column
+types}.
+
+@item
+Very fast joins using an optimized one-sweep multi-join.
+
+@item
+Full operator and function support in the @code{SELECT} and @code{WHERE}
+parts of queries. Example:
+@example
+mysql> SELECT CONCAT(first_name, " ", last_name) FROM tbl_name
+ WHERE income/dependents > 10000 AND age > 30;
+@end example
+
+@item
+SQL functions are implemented through a highly-optimized class library and
+should be as fast as they can get! Usually there shouldn't be any memory
+allocation at all after query initialization.
+
+@item
+Full support for SQL @code{GROUP BY} and @code{ORDER BY}
+clauses. Support for group functions (@code{COUNT()},
+@code{COUNT(DISTINCT)}, @code{AVG()}, @code{STD()}, @code{SUM()},
+@code{MAX()} and @code{MIN()}).
+
+@item
+Support for @code{LEFT OUTER JOIN} with ANSI SQL and ODBC syntax.
+
+@item
+You can mix tables from different databases in the same query (as of
+version 3.22).
+
+@item
+A privilege and password system which is very flexible and secure, and
+which allows host-based verification. Passwords are secure because all
+password traffic when connecting to a server is encrypted.
+
+@item
+ODBC (Open-DataBase-Connectivity) support for Windows95 (with source). All
+ODBC 2.5 functions and many others. For example, you can use Access to
+connect to your @strong{MySQL} server. @xref{ODBC}.
+
+@item
+Very fast B-tree disk tables with index compression.
+
+@item
+16 indexes per table are allowed. Each index may consist of 1 to 16 columns
+or parts of columns. The maximum index length is 256 bytes (this may be
+changed when compiling @strong{MySQL}). An index may use a prefix of a
+@code{CHAR} or @code{VARCHAR} field.
+
+@item
+Fixed-length and variable-length records.
+
+@item
+In-memory hash tables which are used as temporary tables.
+
+@item
+Handles large databases. We are using @strong{MySQL} with some
+databases that contain 50,000,000 records.
+
+@item
+All columns have default values. You can use @code{INSERT} to insert a
+subset of a table's columns; those columns that are not explicitly given
+values are set to their default values.
+
+@item
+Uses GNU Automake, Autoconf, and @code{libtool} for portability.
+
+@item
+Written in C and C++. Tested with a broad range of different compilers.
+
+@item
+A very fast thread-based memory allocation system.
+
+@item
+No memory leaks. Tested with a commercial memory leakage detector
+(@code{purify}).
+
+@item
+Includes @code{myisamchk}, a very fast utility for table checking, optimization
+and repair.
+@xref{Maintenance}.
+
+@item
+Full support for several different character sets, including
+ISO-8859-1 (Latin1), big5, ujis, and more. For example, the
+Scandinavian characters `@ringaccent{a}', `@"a' and `@"o' are allowed
+in table and column names.
+
+@item
+All data are saved in the chosen character set. All comparisons for normal
+string columns are case insensitive.
+
+@item
+Sorting is done according to the chosen character set (the Swedish
+way by default). It is possible to change this when the @strong{MySQL} server
+is started up. To see an example of very advanced sorting, look at the
+Czech sorting code. @strong{MySQL} supports many different character sets
+that can be specified at compile and run time.
+
+@item
+Aliases on tables and columns are allowed as in the SQL92 standard.
+
+@item
+@code{DELETE}, @code{INSERT}, @code{REPLACE}, and @code{UPDATE} return
+how many rows were changed (affected). It is possible to return the number
+of rows matched instead by setting a flag when connecting to the server.
+
+@item
+Function names do not clash with table or column names. For example, @code{ABS}
+is a valid column name. The only restriction is that for a function call, no
+spaces are allowed between the function name and the @samp{(} that follows it.
+@xref{Reserved words}.
+
+@item
+All @strong{MySQL} programs can be invoked with the @code{--help} or @code{-?}
+options to obtain online assistance.
+
+@item
+The server can provide error messages to clients in many
+languages. @xref{Languages}.
+
+@item
+Clients may connect to the @strong{MySQL} server using TCP/IP connections or
+Unix sockets, or named pipes under NT.
+
+@item
+The @strong{MySQL}-specific @code{SHOW} command can be used to retrieve
+information about databases, tables and indexes. The @code{EXPLAIN} command
+can be used to determine how the optimizer resolves a query.
+@end itemize
+
+@cindex Stability
+@node Stability, Year 2000 compliance, Features, Introduction
+@section How stable is MySQL?
+
+This section addresses the questions, ``How stable is
+@strong{MySQL}?'' and, ``Can I depend on @strong{MySQL} in this project?''
+Here we will try to clarify some issues and to answer some of the more
+important questions that seem to concern many people. This section has been
+put together from information gathered from the mailing list (which is very
+active in reporting bugs).
+
+At TcX, @strong{MySQL} has worked without any problems in our projects since
+mid-1996. When @strong{MySQL} was released to a wider public, we noticed that
+there were some pieces of ``untested code'' that were quickly found by the
+new users who made queries in a manner different than our own. Each new
+release has had fewer portability problems than the previous one (even though
+each has had many new features), and we hope that it will be possible to label
+one of the next releases ``stable''.
+
+Each release of @strong{MySQL} has been usable and there have been problems
+only when users start to use code from ``the gray zones''. Naturally, outside
+users can't know what the gray zones are; this section attempts to indicate
+those that are currently known. The descriptions deal with the 3.22.x
+version of @strong{MySQL}. All known and reported bugs are fixed in the
+latest version, with the exception of the bugs listed in the bugs section,
+which are things that are ``design''-related. @xref{Bugs}.
+
+@strong{MySQL} is written in multiple layers and different independent
+modules. These modules are listed below with an indication of how
+well-tested each of them is:
+
+@table @strong
+@item The ISAM table handler --- Stable
+This manages storage and retrieval of all data in @strong{MySQL} 3.22
+and earlier versions. In all @strong{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 an update. Even
+that is unlikely to destroy any data beyond rescue, because all data are
+flushed to disk between each query. There hasn't been a single bug
+report about lost data because of bugs in @strong{MySQL}, either.
+
+@item The MyISAM table handler --- Beta
+This is new in @strong{MySQL} 3.23. It's largely based on the ISAM table code
+but has a lot of new very useful features.
+
+@item The parser and lexical analyser --- Stable
+There hasn't been a single reported bug in this system for a long time.
+
+@item The C client code --- Stable
+No known problems. In early 3.20 releases, there were some limitations in
+the send/receive buffer size. As of 3.21.x, the buffer size is now dynamic up
+to a default of 24M.
+
+@item Standard client programs --- Stable
+These include @code{mysql}, @code{mysqladmin} and @code{mysqlshow},
+@code{mysqldump}, and @code{mysqlimport}.
+
+@item Basic SQL --- Stable
+The basic SQL function system and string classes and dynamic memory
+handling. Not a single reported bug in this system.
+
+@item Query optimizer --- Stable
+
+@item Range optimizer --- Gamma
+
+@item Join optimizer --- Stable
+
+@item Locking --- Gamma
+This is very system-dependent. On some systems there are big problems
+using standard OS locking (@code{fcntl()}). In these cases, you should run the
+@strong{MySQL} daemon with the @code{--skip-locking} flag. Problems are known
+to occur on some Linux systems and on SunOS when using NFS-mounted file
+systems.
+
+@item Linux threads --- Gamma
+The major problem found has been with the @code{fcntl()} call, which is
+fixed by using the @w{@code{--skip-locking}} option to
+@code{mysqld}. Some people have reported lockup problems with the 0.5
+release. LinuxThreads will need to be recompiled if you plan to use
+1000+ concurrent connections. Although it is possible to run that many
+connections with the default LinuxThreads ( however, you will never go
+above 1021 ), the default stack spacing of 2 MB makes the application
+unstable, and we have been able to reproduce a coredump after creating
+1021 idle connections. See Linux Notes for more details.
+
+@item Solaris 2.5+ pthreads --- Stable
+We use this for all our production work.
+
+@item MIT-pthreads (Other systems) --- Gamma
+There have been no reported bugs since 3.20.15 and no known bugs since
+3.20.16. On some systems, there is a ``misfeature'' where some operations are
+quite slow (a 1/20 second sleep is done between each query). Of course,
+MIT-pthreads may slow down everything a bit, but index-based @code{SELECT}
+statements are usually done in one time frame so there shouldn't be a mutex
+locking/thread juggling.
+
+@item Other thread implementions --- Alpha - Beta
+The ports to other systems are still very new and may have bugs, possibly
+in @strong{MySQL}, but most often in the thread implementation itself.
+
+@item @code{LOAD DATA ...}, @code{INSERT ... SELECT} --- Stable
+Some people have thought they have found bugs here, but these usually have
+turned out to be misunderstandings. Please check the manual before reporting
+problems!
+
+@item @code{ALTER TABLE} --- Stable
+Small changes in 3.22.12.
+
+@item DBD --- Stable
+Now maintained by Jochen Wiedmann
+@email{wiedmann@@neckar-alb.de}. Thanks!
+
+@item @code{mysqlaccess} --- Stable
+Written and maintained by Yves Carlier
+@email{Yves.Carlier@@rug.ac.be}. Thanks!
+
+@item @code{GRANT} --- Gamma
+Big changes made in @strong{MySQL} 3.22.12.
+
+@item @strong{MyODBC} (uses ODBC SDK 2.5) --- Gamma
+It seems to work well with some programs.
+@end table
+
+MySQL AB provides email support for paying customers, but the @strong{MySQL}
+mailing list usually provides answers to common questions. Bugs are
+usually fixed right away with a patch; for serious bugs, there is almost
+always a new release.
+
+@cindex Year 2000 compliance
+@node Year 2000 compliance, General-SQL, Stability, Introduction
+@section Year 2000 compliance
+
+@strong{MySQL} itself has no problems with Year 2000 (Y2K) compliance:
+
+@itemize @bullet
+@item
+@strong{MySQL} uses Unix time functions and has no problems with dates
+until @code{2069}; all 2-digit years are regarded to be in the range
+@code{1970} to @code{2069}, which means that if you store @code{01} in a
+@code{year} column, @strong{MySQL} treats it as @code{2001}.
+
+@item
+All @strong{MySQL} date
+functions are stored in one file @file{sql/time.cc} and coded very carefully
+to be year 2000-safe.
+
+@item
+In @strong{MySQL} 3.22 and later versions, the new @code{YEAR} column type
+can store years @code{0} and @code{1901} to @code{2155} in 1 byte and display
+them using 2 or 4 digits.
+@end itemize
+
+You may run into problems with applications that use @strong{MySQL} in a
+way that is not Y2K-safe. For example, many old applications store
+or manipulate years using 2-digit values (which are ambiguous) rather than
+4-digit values. This problem may be compounded by applications that use
+values such as @code{00} or @code{99} as ``missing'' value indicators.
+
+Unfortunately, these problems may be difficult to fix, because different
+applications may be written by different programmers, each of whom may
+use a different set of conventions and date-handling functions.
+
+Here is a simple demonstration illustrating that @strong{MySQL} doesn't have
+any problems with dates until the year 2030!
+
+@example
+mysql> DROP TABLE IF EXISTS y2k;
+mysql> CREATE TABLE y2k (date date, date_time datetime, time_stamp timestamp);
+mysql> INSERT INTO y2k VALUES ("1998-12-31","1998-12-31 23:59:59",19981231235959);
+mysql> INSERT INTO y2k VALUES ("1999-01-01","1999-01-01 00:00:00",19990101000000);
+mysql> INSERT INTO y2k VALUES ("1999-09-09","1999-09-09 23:59:59",19990909235959);
+mysql> INSERT INTO y2k VALUES ("2000-01-01","2000-01-01 00:00:00",20000101000000);
+mysql> INSERT INTO y2k VALUES ("2000-02-28","2000-02-28 00:00:00",20000228000000);
+mysql> INSERT INTO y2k VALUES ("2000-02-29","2000-02-29 00:00:00",20000229000000);
+mysql> INSERT INTO y2k VALUES ("2000-03-01","2000-03-01 00:00:00",20000301000000);
+mysql> INSERT INTO y2k VALUES ("2000-12-31","2000-12-31 23:59:59",20001231235959);
+mysql> INSERT INTO y2k VALUES ("2001-01-01","2001-01-01 00:00:00",20010101000000);
+mysql> INSERT INTO y2k VALUES ("2004-12-31","2004-12-31 23:59:59",20041231235959);
+mysql> INSERT INTO y2k VALUES ("2005-01-01","2005-01-01 00:00:00",20050101000000);
+mysql> INSERT INTO y2k VALUES ("2030-01-01","2030-01-01 00:00:00",20300101000000);
+mysql> INSERT INTO y2k VALUES ("2050-01-01","2050-01-01 00:00:00",20500101000000);
+mysql> SELECT * FROM y2k;
++------------+---------------------+----------------+
+| date | date_time | time_stamp |
++------------+---------------------+----------------+
+| 1998-12-31 | 1998-12-31 23:59:59 | 19981231235959 |
+| 1999-01-01 | 1999-01-01 00:00:00 | 19990101000000 |
+| 1999-09-09 | 1999-09-09 23:59:59 | 19990909235959 |
+| 2000-01-01 | 2000-01-01 00:00:00 | 20000101000000 |
+| 2000-02-28 | 2000-02-28 00:00:00 | 20000228000000 |
+| 2000-02-29 | 2000-02-29 00:00:00 | 20000229000000 |
+| 2000-03-01 | 2000-03-01 00:00:00 | 20000301000000 |
+| 2000-12-31 | 2000-12-31 23:59:59 | 20001231235959 |
+| 2001-01-01 | 2001-01-01 00:00:00 | 20010101000000 |
+| 2004-12-31 | 2004-12-31 23:59:59 | 20041231235959 |
+| 2005-01-01 | 2005-01-01 00:00:00 | 20050101000000 |
+| 2030-01-01 | 2030-01-01 00:00:00 | 20300101000000 |
+| 2050-01-01 | 2050-01-01 00:00:00 | 00000000000000 |
++------------+---------------------+----------------+
+
+13 rows in set (0.00 sec)
+@end example
+
+This shows that the @code{DATE} and @code{DATETIME} types are will not
+give any problems with future dates (they handle dates until the year
+9999).
+
+The @code{TIMESTAMP} type, that is used to store the current time, has a
+range up to only @code{2030-01-01}. @code{TIMESTAMP} has a range of
+@code{1970} to @code{2030} on 32-bit machines (signed value). On 64-bit
+machines it handles times up to @code{2106} (unsigned value).
+
+Even though @strong{MySQL} is Y2K-compliant, it is your responsibility to
+provide unambiguous input. See @ref{Y2K issues} for @strong{MySQL}'s rules
+for dealing with ambiguous date input data (data containing 2-digit year
+values).
+
+@node General-SQL, Useful Links, Year 2000 compliance, Introduction
+@section General SQL information and tutorials
+
+This book has been recommended by a several people on the @strong{MySQL}
+mailing list:
+
+@example
+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
+@end example
+
+This book has also received some recommendations by @strong{MySQL} users:
+
+@example
+Martin Gruber
+Understanding SQL
+ISBN 0-89588-644-8
+Publisher Sybex 510 523 8233
+Alameda, CA USA
+@end example
+
+A SQL tutorial is available on the net at
+http://www.geocities.com/SiliconValley/Vista/2207/sql1.html
+
+SQL in 21 Tagen (online book in German language):
+http://www.mut.de/leseecke/buecher/sql/inhalt.htm
+
+@node Useful Links, , General-SQL, Introduction
+@section Useful MySQL-related links
+
+Apart from the following links, you can find and download a lot of
+@strong{MySQL} programs, tools and APIs from the
+@uref{http://www.mysql.com/Contrib/, Contrib directory}.
+
+@subheading Tutorials
+@itemize @bullet
+
+@item @uref{http://www.devshed.com/resource/advanced/mysql/index.html, A
+beginner's tutorial of how to start using @strong{MySQL}}
+
+@item @uref{http://www.analysisandsolutions.com/code/mybasic.htm}
+Beginners @strong{MySQL} Tutorial on how to install and set up
+@strong{MySQL} on a Windows machine.
+
+@item @uref{http://www.devshed.com/Server_Side/MySQL/, A lot of @strong{MySQL} tutorials}
+
+@item @uref{http://www.linuxplanet.com/linuxplanet/tutorials/1046/1/,
+Setting Up a @strong{MySQL}-Based Website}
+
+@item @uref{http://www.hotwired.com/webmonkey/backend/tutorials/tutorial1.html, @strong{MySQL}-Perl tutorial}
+
+@item @uref{http://www.iserver.com/support/contrib/perl5/modules.html,Installing new Perl modules that require locally installed modules}
+
+@item @uref{http://www.hotwired.com/webmonkey/databases/tutorials/tutorial4.html, PHP/@strong{MySQL} Tutorial}
+
+@item @uref{http://www.useractive.com/, Hands on tutorial for @strong{MySQL}}
+@end itemize
+
+@subheading Porting MySQL / Using MySQL on different systems
+@itemize @bullet
+@item @uref{http://xclave.macnn.com/MySQL/,The MacOS Xclave}.
+Running @strong{MySQL} on MacOSX
+@item @uref{http://www.prnet.de/RegEx/mysql.html, MySql for MacOSX Server}
+@item @uref{http://www.lilback.com/macsql/, Client libraries for the Macintosh}
+@end itemize
+
+@subheading Perl related links
+@itemize @bullet
+@item
+@c Added 991122
+@uref{http://haven.e-cactus.com/dbi_mysql, Perl DBI with @strong{MySQL} FAQ}
+@end itemize
+
+@subheading MySQL discussion forums
+@itemize @bullet
+@item
+@uref{http://www.weberdev.com/, Examples using @strong{MySQL}; (check Top 20)}
+@item
+@uref{http://futurerealm.com/forum/futureforum.htm, FutureForum Web Discussion Software}
+@end itemize
+
+@c We should get longer descriptions for things in this category!
+@subheading Commercial applications that support MySQL
+@itemize @bullet
+@item
+@uref{http://www.supportwizard.com/, SupportWizard; Interactive helpdesk
+on the web (This product includes a licensed copy of @strong{MySQL})}
+@item
+@uref{http://www.stweb.org/, StWeb}
+StWeb - Stratos Web and Application server - an easy-to-use, cross
+platform, Internet/Intranet development and deployment system for
+development of web-enabled applications. The standard version of StWeb
+has a native interface to @strong{MySQL} database.
+@item
+@uref{http://www.rightnowtech.com/, Right Now Web; Web automation for customer service}
+@item
+@uref{http://www.icaap.org/Bazaar/, Bazaar; Interactive Discussion Forums with web interface}
+@item
+@uref{http://www.phonesweep.com/, PhoneSweepT} is the world's first
+commercial Telephone Scanner. Many break-ins in recent years have come
+not through the Internet, but through unauthorized dial-up
+modems. PhoneSweep lets you find these modems by repeatedly placing
+phone calls to every phone number that your organization
+controls. PhoneSweep has a built-in expert system that can recognize
+more than 250 different kinds of remote-access programs, including
+Carbon Copy(TM), pcANYWHERE(TM), and Windows NT RAS. All information is stored
+in the SQL database. It then generates a comprehensive report detailing
+which services were discovered on which dial-up numbers in your
+organization.
+@end itemize
+
+@subheading SQL Clients/Report writers
+
+@itemize @bullet
+@item
+@uref{http://www.urbanresearch.com/software/utils/urbsql/index.html,
+@strong{MySQL} Editor/Utility for MS Windows Platforms.}
+@item
+@uref{http://www.xnot.com/kmysql, KDE @strong{MySQL} client}
+@item
+@c EMAIL: bilhaut_f@mail.cpod.fr (Frédérik Bilhaut)
+@uref{http://www.penguinpowered.com/~kmysql, KMySQL}
+KMySQL is a database client for KDE that primarily supports @strong{MySQL}.
+@item
+@uref{http://www.ecker-software.de, Win32 GUI client}
+A Win32 GUI client by David Ecker.
+@item
+@uref{http://www.icaap.org/software/kiosk/, Kiosk; a @strong{MySQL} client for
+database management}. Written in Perl. Will be a part of Bazaar.
+@item
+@uref{http://www.geocities.com/SiliconValley/Ridge/4280/GenericReportWriter/grwhome.html, A free report writer in Java}
+@item
+@uref{http://www.javaframework.de,MySQLExport}
+Export of @strong{MySQL} create statements and data in a lot of
+different formats (SQL, HTML, CVS, text, ZIP, GZIP...)
+@end itemize
+
+@subheading Distributions that include MySQL
+
+@itemize @bullet
+@item
+@uref{http://www.suse.com/, SuSE Linux (Suse 6.1 and above)}
+@end itemize
+
+@subheading Web development tools that support @strong{MySQL}
+
+@itemize @bullet
+@item
+@uref{http://www.php.net/, PHP: A server-side HTML-embedded scripting
+language}
+@item
+@uref{http://www.midgard-project.org, The Midgard Application Server; a
+powerful Web development environment based on @strong{MySQL} and PHP}
+@item
+@uref{http://www.smartworker.org, SmartWorker is a platform for web application development}
+@item
+@uref{http://xsp.lentus.se/, XSP: e(X)tendible (S)erver (P)ages and is a
+HTML embedded tag language written in Java (previously known as XTAGS)}
+@item
+@uref{http://www.dbServ.de/, dbServ} is an extension to a web server to
+integrate databases output into your HTML code. You may use any HTML
+function in your output. Only the client will stop you. It works as
+standalone server or as JAVA servlet.
+@item
+@uref{http://www.chilisoft.com/, Platform independent ASP from Chili!Soft}
+@c @item
+@c no answer from server 990830
+@c @uref{http://www.voicenet.com/~zellert/tjFM, A JDBC driver for @strong{MySQL}}
+@item
+@uref{http://www.wernhart.priv.at/php/, @strong{MySQL} + PHP demos}
+@item
+@uref{http://www.dbwww.com/, ForwardSQL: HTML interface to manipulate @strong{MySQL} databases}
+@item
+@uref{http://www.daa.com.au/~james/www-sql/, WWW-SQL: Display database
+information}
+@item
+@uref{http://www.minivend.com/minivend/, Minivend: A Web shopping cart}
+@item
+@uref{http://www.heitml.com/, HeiTML: A server-side extension of HTML and
+a 4GL language at the same time}
+@item
+@uref{http://www.metahtml.com/, Metahtml: A Dynamic Programming Language
+for WWW Applications}
+@item
+@uref{http://www.binevolve.com/, VelocityGen for Perl and Tcl}
+@item
+@uref{http://hawkeye.net/, Hawkeye Internet Server Suite}
+@item
+@uref{http://www.fastflow.com/, Network Database Connection For Linux}
+@item
+@uref{http://www.wdbi.net/,
+WDBI: Web browser as a universal front end to databases which supports
+@strong{MySQL} well.}
+@item
+@uref{http://www.webgroove.com/, WebGroove Script: HTML compiler and server-side scripting language}
+@item
+@uref{http://www.ihtml.com/, A server-side web site scripting language}
+@item
+@uref{ftp://ftp.igc.apc.org/pub/myodbc/README, How to use @strong{MySQL} with ColdFusion on Solaris}
+@item
+@uref{http://calistra.com/MySQL/,Calistra's ODBC @strong{MySQL} Administrator}
+@item
+@uref{http://www.webmerger.com, Webmerger}
+This CGI tool interprets files and generates dynamic output
+based on a set of simple tags. Ready-to-run drivers for @strong{MySQL} and PostgreSQL
+through ODBC.
+@item
+@uref{http://phpclub.unet.ru/index_e.php3, PHPclub}. Tips and tricks for PHP
+@item
+@uref{http://www.penguinservices.com/scripts, @strong{MySQL} and Perl Scripts}
+@item
+@uref{http://www.widgetchuck.com, The Widgetchuck; Web Site Tools and Gadgets}
+@item
+@uref{http://www.adcycle.com/, AdCycle} advertising management software
+@item
+@uref{http://www.bidsystems.com/pwPage, pwPage} provides an extremely
+fast and simple approach to the creation of database forms. That is,
+if a database table exists and an HTML page has been constructed using
+a few simple guidelines, pwPage can be immediately used for table data
+selections, insertions, updates, deletions and selectable table content
+reviewing.
+@item
+@uref{http://www.omnis-software.com/products/studio/studio.html, OMNIS}
+OMNIS Studio is a rapid application development (RAD) tool.
+@end itemize
+
+@subheading Database design tools with MySQL support
+@itemize @bullet
+@item
+@uref{http://www.mysql.com/dezign/index.html, "DeZign for
+databases" is a database development tool using an
+entity relationship diagram (ERD).}
+@end itemize
+
+@subheading Web servers with @strong{MySQL} tools
+
+@itemize @bullet
+@item
+@uref{http://bourbon.netvision.net.il/mysql/mod_auth_mysql/, An Apache
+authentication module}
+@item
+@uref{http://www.roxen.com/, The Roxen Challenger Web server}
+@end itemize
+
+@subheading Extensions for other programs
+
+@itemize @bullet
+@item
+@uref{http://www.seawood.org/msql_bind/, @strong{MySQL} support for BIND
+(The Internet Domain Name Server)}
+@item
+@uref{http://www.inet-interactive.com/sendmail, @strong{MySQL} support for
+Sendmail and Procmail}
+@end itemize
+
+@subheading Using @code{MySQL} with other programs
+
+@itemize @bullet
+@item
+@uref{http://www.iserver.com/support/addonhelp/database/mysql/msaccess.html, Using @strong{MySQL} with Access}
+@item
+@uref{http://www.iserver.com/support/contrib/perl5/modules.html,Installing new Perl modules that require locally installed modules}
+@end itemize
+
+@subheading ODBC related links
+
+@itemize @bullet
+@item
+@uref{http://www.iodbc.org/,Popular iODBC Driver Manager (libiodbc) now available in Open Source format}
+@item
+@uref{http://users.ids.net/~bjepson/freeODBC/,The FreeODBC Pages}
+@item
+@uref{http:/http://genix.net/unixODBC/,unixodbc}
+The unixODBC Project goals are to develop and promote unixODBC to be the
+definitive standard for ODBC on the Linux platform.
+This is to include GUI support for KDE.
+@item
+@uref{http://www.sw-soft.com/products/BtrieveODBC/}
+A @strong{MySQL}-based ODBC drivers for Btrieve
+@end itemize
+
+@subheading @strong{API} related links
+
+@itemize @bullet
+@item
+@uref{http://www.amedea.cz/mysqlx/index.html, MySQL COM extension}
+With this COM objects You can use MySQL also on Windows platform with ASP
+pages or Delphi, Visual Basic, Visual C++, ... languages.
+@item
+@uref{http://www.jppp.com, www.jppp.com}
+Partially implemented TDataset-compatible components for @strong{MySQL}.
+@item
+@uref{http://www.riverstyx.net/qpopmysql/,qpopmysql}
+A patch to allow POP3 authentication from a @strong{MySQL} database.
+There's also a link to Paul Khavkine's patch for Procmail to allow
+any MTA to deliver to users in a @strong{MySQL} database.
+@item
+@uref{http://www.pbc.ottawa.on.ca,Visual Basic class generator for Active X}
+@item
+@uref{http://www.lilback.com/macsql/, Client libraries for the Macintosh}
+@c @item
+@c @uref{http://tfdec1.fys.kuleuven.ac.be/~michael/fpc-linux/mysql,
+@c @strong{MySQL} binding to Free Pascal}
+@item
+@uref{http://www.dedecker.net/jessie/scmdb/, SCMDB}.
+SCMDB is an add-on for SCM that ports the mysql C library to scheme (SCM).
+With this library scheme developers can make connections to a mySQL
+database and use embedded SQL in their programs.
+@end itemize
+
+@subheading Other @strong{MySQL}-related links
+
+@itemize @bullet
+@item
+@uref{http://www.wix.com/mysql-hosting, Registry of Web providers who
+support @strong{MySQL}}
+@item
+@uref{http://www.softagency.co.jp/mysql/index.en.phtml, Links about using
+@strong{MySQL} in Japan/Asia}
+@item
+@uref{http://www.open.com.au/products.html, Commercial Web defect tracking
+system}
+@item
+@uref{http://www.stonekeep.com/pts/, PTS: Project Tracking System}
+@item
+@uref{http://tomato.nvgc.vt.edu/~hroberts/mot, Job and software tracking
+system}
+@c @item
+@c Error 404 990830
+@c @uref{http://home.wxs.nl/cgi-bin/planeteers/pgidszoek.cgi, Full-text search engine using @strong{MySQL}}
+@item
+@uref{http://www.cynergi.net/non-secure/exportsql/, ExportSQL: A script
+to export data from Access95+}
+@item
+@uref{http://SAL.KachinaTech.COM/H/1/MYSQL.html, SAL (Scientific
+Applications on Linux) @strong{MySQL} entry}
+@c Removed 990510
+@c @item
+@c @uref{http://www.cgishop.com/bin/mysqllist, @strong{MySQL} Apps and
+@c Utilities Listing}
+@c @item
+@c @uref{http://www.luth.se/~goggi/proj/mysql/man/mysql.pdf, The
+@c @strong{MySQL} reference manual in Adobe PDF format}
+@item
+@uref{http://www.infotech-nj.com/itech/index.shtml, A consulting company
+which mentions @strong{MySQL} in the right company}
+@item
+@uref{http://www.pmpcs.com/, PMP Computer Solutions. Database developers using
+@strong{MySQL} and @code{mSQL}}
+@item
+@uref{http://www.aewa.org, Airborne Early Warning Association }
+@item
+@uref{http://abattoir.cc.ndsu.nodak.edu/~nem/mysql/udf/, @strong{MySQL} UDF Registry}
+@item
+@uref{http://21ccs.com/~gboersm/y2kmatrix/, Y2K tester}
+@end itemize
+
+@subheading SQL and database interfaces
+@itemize @bullet
+@item
+@uref{http://java.sun.com/products/jdbc/, The JDBC database access API}
+@item
+@uref{http://www.gagme.com/mysql, Patch for @code{mSQL} Tcl}
+@item
+@uref{http://www.amsoft.ru/easysql/, EasySQL: An ODBC-like driver manager}
+@item
+@uref{http://www.lightlink.com/hessling/rexxsql.html, A REXX interface to SQL databases}
+@item
+@uref{http://www.binevolve.com/~tdarugar/tcl-sql, Tcl interface}
+@end itemize
+
+@subheading Examples of MySQL use
+
+@itemize @bullet
+@item
+@c Added 990601
+@c EMAIL: thuss@little6.com (Todd Huss)
+@uref{http://www.little6.com/about/linux/, Little6 Inc} An online contract and job finding site that is powered by @strong{MySQL}, PHP3 and Linux.
+@item
+@c Added 990521
+@c EMAIL: nh@delec.com (Hillbrecht Nicole)
+@uref{http://www.delec.com/is/products/prep/examples/BookShelf/index.html, DELECis} A tool which makes it very easy to create an automatically generated table documentation. They have used @strong{MySQL} as an example.
+@c @item
+@c Added 990531. Removed 000201 -> No answer from server
+@c EMAIL: sfambro@hotmail.com (Steve Fambro)
+@c @uref{http://shredder.elen.utah.edu/steve.html, Steve Fambro}
+@c Uses @strong{MySQL} and webmerger. There is an employee database, and a
+@c license plate database with all of the registered Utah vehicles (over
+@c 1.2 million). The License plate field is indexed.....so the *searches*
+@c are instantaneous.
+@item
+@c Added 990521
+@c EMAIL: info@worldrecords.com (Jim Rota)
+@uref{http://www.worldrecords.com, World Records} A search engine for information about music that uses @strong{MySQL} and PHP.
+@item
+@uref{http://www.webtechniques.com/archives/1998/01/note/,
+A Contact Database using @strong{MySQL} and PHP}
+@item
+@uref{http://modems.rosenet.net/mysql/, Web based interface and Community Calender with PHP}
+@item
+@uref{http://www.odbsoft.com/cook/sources.htm, Perl package to generate html from a SQL table structure and for generating SQL statements from an html form.}
+@item
+@uref{http://www.gusnet.cx/proj/telsql/,Basic telephone database using @code{DBI}/@code{DBD}}.
+@item
+@uref{http://tecfa.unige.ch/guides/java/staf2x/ex/jdbc/coffee-break, JDBC examples by Daniel K. Schneider}
+@item
+@uref{http://www.spade.com/linux/howto/PostgreSQL-HOWTO-41.html,SQL BNF}
+@item
+@uref{http://www.ooc.com/, Object Oriented Concepts Inc; CORBA applications with examples in source}
+@item
+@uref{http://www.pbc.ottawa.on.ca/,DBWiz; Includes an example of how to manage own cursors in VB}
+@item
+@uref{http://keilor.cs.umass.edu/pluribus/, Pluribus}
+Pluribus, is a free search engine that learns to improve
+the quality of its results over time. Pluribus works by recording
+which pages a user prefers among those returned for a query. A user
+votes for a page by selecting it; Pluribus then uses that knowledge
+to improve the quality of the results when someone else submits the
+same (or similar) query. Uses PHP and @strong{MySQL}.
+@item
+@c EMAIL: paul@sword.damocles.com (Paul Bannister)
+@uref{http://www.stopbit.com/, Stopbit}
+A technology news site using @strong{MySQL} and PHP
+@item
+@c Added 990604
+@c EMAIL: ah@dybdahl.dk
+@uref{http://www.jokes2000.com/scripts/, Example scripts at Jokes2000}
+@item
+@uref{http://www.linuxsupportline.com/~kalendar/ KDE based calendar manager}
+The calendar manager has both single user (file based) and multi user
+(@strong{MySQL} database) support.
+@item
+@uref{http://tim.desert.net/~tim/imger/,Example of storing/retrieving images with @strong{MySQL} and CGI}
+@item
+@uref{http://www.penguinservices.com/scripts, Online shopping cart system}
+@item
+@c Added 990928 from editor@city-gallery.com
+@uref{http://www.city-gallery.com/album/, Old Photo Album}
+The album is a collaborative popular history of photography project that
+generates all pages from data stored in a @strong{MySQL} database. Pages are
+dynamically generated through a php3 interface to the database content.
+Users contribute images and descriptions. Contributed images are stored
+on the web server to avoid storing them in the database as BLOBs. All
+other information is stored in on the shared @strong{MySQL} server.
+@end itemize
+
+@subheading General database links
+@itemize @bullet
+@item
+@uref{http://www.pcslink.com/~ej/dbweb.html, Database Jump Site}
+@item
+@uref{http://black.hole-in-the.net/guy/webdb/, Homepage of the webdb-l
+(Web Databases) mailing list.}
+@item
+@uref{http://www.symbolstone.org/technology/perl/DBI/index.html,
+Perl @code{DBI}/@code{DBD} modules homepage}
+@item
+@uref{http://www.student.uni-koeln.de/cygwin/, Cygwin tools. UNIX on top of Windows}
+@item
+@uref{http://dbasecentral.com/, dbasecentral.com; Development and distribution of powerful and easy-to-use database applications and systems.}
+@item
+@uref{http://www.Tek-Tips.com, Tek-Tips Forums} Tek-Tips Forums are 800+
+independent peer-to-peer non-commercial support forums for Computer
+Professionals. Features include automatic e-mail notification of
+responses, a links library, and member confidentiality guaranteed.
+@end itemize
+
+There are also many web pages that use
+@strong{MySQL}. @xref{Users}. Send any additions to this list to
+@email{webmaster@@mysql.com}. We now require that you show a
+@strong{MySQL} logo somewhere (It is okay to have it on a ``used tools'' page
+or something similar) to be added.
+
+@cindex Reporting errors
+@cindex @strong{MySQL} mailing lists
+@node Questions, Licensing and Support, Introduction, Top
+@chapter MySQL mailing lists and how to ask questions or report errors (bugs)
+
+@menu
+* Mailing-list:: The @strong{MySQL} mailing lists
+* Asking questions:: Asking questions or reporting bugs
+* Bug reports:: How to report bugs or problems
+* Answering questions:: Guidelines for answering questions on the mailing list
+@end menu
+
+@node Mailing-list, Asking questions, Questions, Questions
+@section The MySQL mailing lists
+
+To subscribe to the main @strong{MySQL} mailing list, send a message to the
+electronic mail address @email{mysql-subscribe@@lists.mysql.com}.
+
+To unsubscribe from the main @strong{MySQL} mailing list, send a message to
+the electronic mail address @email{mysql-unsubscribe@@lists.mysql.com}.
+
+Only the address to which you send your messages is significant. The
+subject line and the body of the message are ignored.
+
+@c the last two addresses in this paragraph are NOT @email because they
+@c shouldn't be live links.
+If your reply address is not valid, you can specify your address explicitly.
+Adding a hyphen to the subscribe or unsubscribe command word, followed by
+your address with the @samp{@@} character in your address replaced by a
+@samp{=}. For example, to subscribe @code{john@@host.domain}, send a message
+to @code{mysql-subscribe-john=host.domain@@lists.mysql.com}.
+
+Mail to @email{mysql-subscribe@@lists.mysql.com} or
+@email{mysql-unsubscribe@@lists.mysql.com} is handled automatically by the
+ezmlm mailing list processor. Information about ezmlm is available at
+@uref{http://www.ezmlm.org, The ezmlm Website}.
+
+To post a message to the list itself, send your message to
+@code{mysql@@lists.mysql.com}. However, please @emph{do not} send mail about
+subscribing or unsubscribing to @email{mysql@@lists.mysql.com}, because any
+mail sent to that address is distributed automatically to thousands of other
+users.
+
+Your local site may have many subscribers to @email{mysql@@lists.mysql.com}.
+If so, it may have a local mailing list, so that messages sent from
+@code{lists.mysql.com} to your site are propagated to the local list. In such
+cases, please contact your system administrator to be added to or dropped
+from the local @strong{MySQL} list.
+
+The following @strong{MySQL} mailing lists exist:
+
+@table @code
+@item announce
+This is for announcement of new versions of @strong{MySQL} and related
+programs. This is a low volume list that we think all @strong{MySQL}
+users should be on.
+
+@item mysql
+The main list for general @strong{MySQL} discussion. Please note that some
+topics are better discussed on the more-specialized lists. If you post to the
+wrong list, you may not get an answer!
+
+@item mysql-digest
+The @code{mysql} list in digest form. That means you get all individual
+messages, sent as one large mail message once a day.
+
+@item bugs
+On this list you should only post a full, repeatable bug report, using
+the @code{mysqlbug} script (if you are running on Windows, you should
+include a description of the operating system and the @strong{MySQL} version).
+Preferably, you should test the problem using the latest stable or
+development version of @strong{MySQL} before posting!
+Anyone should be able to repeat the bug by just using 'mysql test <
+script' on the included test case. All bugs posted on this list will be
+corrected or documented in the next @strong{MySQL} release! If there are only
+small code changes involved, we will also post a patch that fixes the problem.
+
+@item bugs-digest
+The @code{bugs} list in digest form
+
+@item developer
+A list for people who work on the @strong{MySQL} code. On this list one
+can also discuss @strong{MySQL} development and post patches.
+
+@item developer-digest
+A digest version of the @code{developer} list.
+
+@item java
+Discussion about @strong{MySQL} and Java. Mostly about the JDBC drivers.
+
+@item java-digest
+A digest version of the @code{java} list.
+
+@item win32
+All things concerning @strong{MySQL} on Microsoft operating systems such as
+Windows NT.
+
+@item win32-digest
+A digest version of the @code{win32} list.
+
+@item myodbc
+All things concerning connecting to @strong{MySQL} with ODBC.
+
+@item myodbc-digest
+A digest version of the @code{myodbc} list.
+
+@item plusplus
+All things concerning programming with the C++ API to @strong{MySQL}.
+
+@item plusplus-digest
+A digest version of the @code{plusplus} list.
+
+@item msql-mysql-modules
+A list about the Perl support in @strong{MySQL}.
+
+@item msql-mysql-modules-digest
+A digest version of the @code{msql-mysql-modules} list.
+@end table
+
+You subscribe or unsubscribe to all lists in the same way as described
+above. In your subscribe or unsubscribe message, just put the appropriate
+mailing list name rather than @code{mysql}. For example, to subscribe to or
+unsubscribe from the @code{myodbc} list, send a message to
+@email{myodbc-subscribe@@lists.mysql.com} or
+@email{myodbc-unsubscribe@@lists.mysql.com}.
+
+@cindex Net etiquette
+@node Asking questions, Bug reports, Mailing-list, Questions
+@section Asking questions or reporting bugs
+
+Before posting a bug report or question, please do the following:
+
+@itemize @bullet
+@item
+Start by searching the @strong{MySQL} online manual at:
+
+@example
+@uref{http://www.mysql.com/documentation/manual.php}
+@end example
+
+We try to keep the manual up to date by
+updating it frequently with solutions to newly found problems!
+
+@item
+Search the @strong{MySQL} mailing list archives:
+
+@example
+@uref{http://www.mysql.com/documentation/}
+@end example
+
+@item
+You can also use @uref{http://www.mysql.com/search.html} to search all the
+web pages (including the manual) that are located at
+@uref{http://www.mysql.com/}.
+@end itemize
+
+If you can't find an answer in the manual or the archives, check with your
+local @strong{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
+@email{mysql@@lists.mysql.com}.
+
+@cindex Bug reports
+@cindex Reporting bugs
+@node Bug reports, Answering questions, Asking questions, Questions
+@section How to report bugs or problems
+
+Writing a good bug report takes patience, but doing it right the first
+time saves time for us and for you. A good bug report containing a full
+test case for the bug will make it very likely that we will fix it in
+the next release. This section will help you write your report correctly
+so that you don't waste your time doing things that may not help us much
+or at all.
+
+We encourage everyone to use the @code{mysqlbug} script to generate a bug
+report (or a report about any problem), if possible. @code{mysqlbug} can be
+found in the @file{scripts} directory in the source distribution, or, for a
+binary distribution, in the @file{bin} directory under your @strong{MySQL}
+installation directory. If you are unable to use @code{mysqlbug}, you should
+still include all the necessary information listed in this section.
+
+The @code{mysqlbug} script helps you generate a report by determining much
+of the following information automatically, but if something important is
+missing, please include it with your message! Please read this section
+carefully and make sure that all the information described here is included
+in your report.
+
+If you can make a test case which clearly shows the bug, you should post
+it to the @email{bugs@@list.mysql.com} list. Note that on this list you
+should only post a full, repeatable bug report, using the @code{mysqlbug}
+script (if you are running on Windows, you should include a
+description of the operating system and the @strong{MySQL} version).
+Preferably, you should test the problem using the latest stable or development
+version of @strong{MySQL} before posting! Anyone should be able to repeat the
+bug by just using 'mysql test < script' on the included test case or run
+the shell / perl script that is included in the bug report. All bugs
+posted on this list will be corrected or documented in the next @strong{MySQL}
+release! If there are only small code changes involved, to correct this
+problem, we will also post a patch that fixes the problem.
+
+Remember that it is possible to respond to a message containing too much
+information, but not to one containing too little. Often people omit facts
+because they think they know the cause of a problem and assume that some
+details don't matter. A good principle is: if you are in doubt about stating
+something, state it! It is a thousand times faster and less troublesome to
+write a couple of lines more in your report than to be forced to ask again
+and wait for the answer because you didn't include enough information the
+first time.
+
+The most common errors are that people don't indicate the version number of
+the @strong{MySQL} distribution they are using, or don't indicate what
+platform they have @strong{MySQL} installed on (including the platform
+version number). This is highly relevant information and in 99 cases out of
+100 the bug report is useless without it! Very often we get questions like
+``Why doesn't this work for me?'' and then we find that the feature
+requested wasn't implemented in that @strong{MySQL} version, or that a bug
+described in a report has been fixed already in newer @strong{MySQL}
+versions. Sometimes the error is platform dependent; in such cases, it is
+next to impossible to fix anything without knowing the operating system and
+the version number of the platform.
+
+Remember also to provide information about your compiler, if it is related to
+the problem. Often people find bugs in compilers and think the problem is
+@strong{MySQL} related. Most compilers are under development all the time and
+become better version by version, too. To determine whether or not your
+problem depends on your compiler, we need to know what compiler is used.
+Note that every compiling problem should be regarded as a bug report and
+reported accordingly.
+
+It is most helpful when a good description of the problem is included in the
+bug report. That is, a good example of all the things you did that led to
+the problem and the problem itself exactly described. The best reports are
+those that include a full example showing how to reproduce the bug or
+problem.
+
+If a program produces an error message, it is very important to include the
+message in your report! If we try to search for something from the archives
+using programs, it is better that the error message reported exactly matches
+the one that the program produces. (Even the case sensitivity should be
+observed!) You should never try to remember what the error message was;
+instead, copy and paste the entire message into your report!
+
+If you have a problem with MyODBC, you should try to genereate a MyODBC
+trace file. @xref{MyODBC bug report}.
+
+Please remember that many of the people who will read your report will
+do so using an 80-column display. When generating reports or examples
+using the @code{mysql} command line tool, you should therefore use
+the @code{--vertical} option (or the @code{\G} statement terminator)
+for output which would exceed the available width for such a display
+(for example, with the @code{EXPLAIN SELECT} statement; see the
+example below).
+
+Please include the following information in your report:
+
+@itemize @bullet
+@item
+The version number of the @strong{MySQL} distribution you are using (for
+example, @strong{MySQL} 3.22.22). You can find out which version you are
+running by executing @code{mysqladmin version}. @code{mysqladmin} can be
+found in the @file{bin} directory under your @strong{MySQL} installation
+directory.
+
+@item
+The manufacturer and model of the machine you are working on.
+
+@item
+The operating system name and version. For most operating systems, you can
+get this information by executing the Unix command @code{uname -a}.
+
+@item
+Sometimes the amount of memory (real and virtual) is relevant.
+If in doubt, include these values.
+
+@item
+If you are using a source distribution of @strong{MySQL}, the name and
+version number of the compiler used is needed.
+If you have a binary distribution, the distribution name is needed.
+
+@item
+If the problem occurs during compilation, include the exact error
+message(s) and also a few lines of context around the offending code in the
+file where the error occurred.
+
+@item
+If any database table is related to the problem, include the output from
+@code{mysqldump --no-data db_name tbl_name1 tbl_name2 ...} This is very easy
+to do and is a powerful way to get information about any table in a database
+that will help us create a situation matching the one you have.
+
+@item
+For speed-related bugs or problems with @code{SELECT} statements, you should
+always include the output of @code{EXPLAIN SELECT ...}, and at least the
+number of rows that the @code{SELECT} statement produces. The more
+information you give about your situation, the more likely it is that someone
+can help you! For example, the following is an example of a very good bug
+report (it should of course be posted with the @code{mysqlbug} script):
+
+Example run using the @code{mysql} command line tool (note the use of the
+@code{\G} statement terminator for statements whose output width would
+otherwise exceed that of an 80-column display device):
+
+@example
+mysql> SHOW VARIABLES;
+mysql> SHOW COLUMNS FROM ...\G
+ <output-from-SHOW-COLUMNS>
+mysql> EXPLAIN SELECT ...\G
+ <output-from-EXPLAIN>
+mysql> FLUSH STATUS;
+mysql> SELECT ...;
+ <A short version of the output from SELECT,
+ including the time taken to run the query>
+mysql> SHOW STATUS;
+ <output from SHOW STATUS>
+@end example
+
+@item
+If a bug or problem occurs while running @strong{MySQL}, try to provide an
+input script that will reproduce the anomaly. This script should include any
+necessary source files. The more closely the script can reproduce your
+situation, the better.
+
+If you can't provide a script, you should at least include the output
+from @code{mysqladmin variables extended-status processlist} in your mail to
+provide some information of how your system is performing!
+
+@item
+If you think that @strong{MySQL} produces a strange result from a query,
+include not only the result, but also your opinion of what the result
+should be and an account describing the basis for your opinion.
+
+@item
+When giving an example of the problem, it's better to use the variable names,
+table names, etc., that exist in your actual situation than to come up with
+new names. The problem could be related to the name of a variable, table,
+etc.! These cases are rare, perhaps, but it is better to be safe than
+sorry. After all, it should be easier for you to provide an example that
+uses your actual situation and it is by all means better for us. In case you
+have data you don't want to show to others, you can use @code{ftp} to
+transfer it to @uref{ftp://support.mysql.com/pub/mysql/secret/}. If the data are
+really top secret and you don't want to show them even to us, then go ahead
+and provide an example using other names, but please regard this as the last
+choice.
+
+@item
+Include all the options given to the relevant programs, if possible. For
+example, indicate the options that you use when you start the @code{mysqld}
+daemon and that you use to run any @strong{MySQL} client programs. The
+options to programs like @code{mysqld} and @code{mysql}, and to the
+@code{configure} script are often keys to answers and very relevant! It is
+never a bad idea to include them anyway! If you use any modules, such as
+Perl or PHP, please include the version number(s) of those as well.
+
+@item
+If you can't produce a test case in a few rows, or if the test table
+is too big to be mailed to the mailing list (more than 10 rows), you should
+dump your tables using @code{mysqldump} and create a @file{README} file
+that describes your problem.
+
+Create a compressed archive of your files using
+@code{tar} and @code{gzip} or @code{zip}, and use @code{ftp}
+to transfer the archive to @uref{ftp://support.mysql.com/pub/mysql/secret/}.
+Then send a short description of the problem to @email{mysql@@lists.mysql.com}.
+
+@item
+If your question is related to the privilege system, please include the
+output of @code{mysqlaccess}, the output of @code{mysqladmin reload} and all
+the error messages you get when trying to connect! When you test your
+privileges, you should first run @code{mysqlaccess}. After this, execute
+@code{mysqladmin reload version}, and last you should try to connect with the
+program that gives you trouble. @code{mysqlaccess} can be found in the
+@file{bin} directory under your @strong{MySQL} installation directory.
+
+@item
+If you have a patch for a bug, that is good, but don't assume the patch is
+all we need, or that we will use it even if you don't provide some necessary
+information such as test cases showing the bug that your patch fixes. We
+might find problems with your patch or we might not understand it at all; if
+so, we can't use it.
+
+If we can't verify exactly what the patch is meant for, we won't use it.
+Test cases will help us here. Show that the patch will handle all the
+situations that may occur. If we find a borderline case (even a rare one)
+where the patch won't work, the patch may be useless.
+
+@item
+Guesses about what the bug is, why it occurs, or what it depends on,
+are usually wrong. Even we can't guess such things without first
+using a debugger to determine the real cause of a bug.
+
+@item
+Indicate in your mail message that you have checked the reference manual
+and mail archive so others know that you have tried to solve your
+problem yourself.
+
+@item
+If you get a @code{parse error}, please check your syntax closely! If
+you can't find something wrong with it, it's extremely likely that your
+current version of @strong{MySQL} doesn't support the query you are
+using. If you are using the current version and the manual at
+@uref{http://www.mysql.com/documentation/manual.php} doesn't cover the syntax you are
+using, @strong{MySQL} doesn't support your query. In this case, your
+only options are to implement the syntax yourself or email
+@email{mysql-licensing@@mysql.com} and ask for an offer to implement it!
+
+If the manual covers the syntax you are using, but you have an older version
+of @strong{MySQL}, you should check the @strong{MySQL} change history to see
+when the syntax was implemented. @xref{News}. In this case, you have the
+option of upgrading to a newer version of @strong{MySQL}.
+
+@item
+If you have a problem such that your data appears corrupt or you get
+errors when you access some particular table, you should first check and then
+try repairing your tables with @code{myisamchk}.
+@xref{Maintenance}.
+
+@item
+If you often get corrupted tables you should try to find out when and
+why this happens! In this case, the
+@file{mysql-data-directory/'hostname'.err} file may contain some
+information about what happened. Please include any relevant
+information from this file in your bug report! Normally @code{mysqld}
+should @strong{NEVER} crash a table if nothing killed it in the middle
+of an update! If you can find the source of why @code{mysqld} dies,
+it's much easier for us to provide you with a fix for the problem!
+@xref{What is crashing}.
+
+@item
+If possible, download the most recent version of @strong{MySQL} and check
+whether or not it solves your problem. All versions of @strong{MySQL} are
+thoroughly tested and should work without problems! We believe in making
+everything as backward compatible as possible and you should be able to
+switch @strong{MySQL} versions in minutes! @xref{Which version}.
+@end itemize
+
+If you are a support customer, please cross-post the bug report to
+@email{mysql-support@@mysql.com} for higher priority treatment, as well as to
+the appropriate mailing list to see if someone else has experienced (and
+perhaps solved) the problem.
+
+For information on reporting bugs in @strong{MyODBC}, see @ref{ODBC
+Problems}.
+
+For solutions to some common problems, see @xref{Problems}.
+
+When answers are sent to you individually and not to the mailing list,
+it is considered good etiquette to summarize the answers and send the
+summary to the mailing list so that others may have the benefit of
+responses you received that helped you solve your problem!
+
+@cindex Net etiquette
+@node Answering questions, , Bug reports, Questions
+@section Guidelines for answering questions on the mailing list
+
+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. Try to make your answer general enough that people other than the
+original poster may benefit from it. When you post to the list, please make
+sure that your answer is not a duplication of a previous answer.
+
+Try to summarize the essential part of the question in your reply; don't feel
+obliged to quote the entire original message.
+
+Please don't post mail messages from your browser with HTML mode turned on!
+Many users don't read mail with a browser!
+
+@cindex Licensing terms
+@cindex Support terms
+@node Licensing and Support, Installing, Questions, Top
+@chapter MySQL licensing and support
+
+@menu
+* Licensing policy:: @strong{MySQL} licensing policy
+* Copyright:: Copyrights used by @strong{MySQL}
+* Licensing examples:: Example licensing situations
+* Cost:: @strong{MySQL} licensing and support costs
+* Support:: Types of commercial support
+@end menu
+
+This chapter describes @strong{MySQL} support and licensing
+arrangements:
+
+@itemize @bullet
+
+@item The copyrights under which @strong{MySQL} is distributed
+(@pxref{Copyright})
+
+@item Sample situations illustrating when a license is required
+(@pxref{Licensing examples})
+
+@item Support costs (@pxref{Cost}), and support benefits
+(@pxref{Support})
+
+@item Commercial licensing costs
+@end itemize
+
+@cindex Licensing policy
+@node Licensing policy, Copyright, Licensing and Support, Licensing and Support
+@section MySQL licensing policy
+
+The formal terms of the GPL license can be found at @ref{GPL license}.
+Basically, our licensing policy and intepretation of the GPL is as follows:
+
+Note that older versions of @strong{MySQL} are still using a more strict
+license. See the documentation for that version for more information.
+If you need a commercial @strong{MySQL} license, because the GPL license
+doesn't suit your application, you can buy one at
+https://order.mysql.com/license.htmy.
+
+For normal internal use, @strong{MySQL} costs nothing. You do not have
+to pay us if you do not want to.
+
+@heading A license is required if:
+
+@itemize @minus
+@item
+You link a part of the of @strong{MySQL} that has a GPL Copyright to a
+program which is not free software (embedded usage of the @strong{MySQL}
+server). In this case your application would also become GPL through the
+clause in the GPL license that acts as a virus. By licensing
+@strong{MySQL} from us under a commercial license you will avoid this
+problem.
+
+@item
+You have a commercial application that ONLY works with @strong{MySQL}
+and ships the application with the @strong{MySQL} server. This is
+because we view this a linking even if it is done over the network.
+
+@item You have a distribute @code{MySQL} and you don't provide the
+source code for your copy of the @strong{MySQL} server, as defined in
+the GPL license.
+@end itemize
+
+@heading A license is @strong{NOT} required if:
+
+@itemize @minus
+
+@item
+You do not need a license to include the client code in commercial
+programs. The client access part of @strong{MySQL} licensed with the
+LGPL @code{GNU Library General Public License}. The @code{mysql} command
+line client includes code from the @code{readline} library that is under
+the @code{GPL}.
+
+@item
+If your use of @strong{MySQL} does not require a license, but you
+like @strong{MySQL} and want to encourage further development, you are
+certainly welcome to purchase a license or @strong{MySQL} support anyway.
+
+@item
+If you use @strong{MySQL} in a commercial context such that
+you profit by its use, we ask that you further the development of
+@strong{MySQL} by purchasing some level of support. We feel that if
+@strong{MySQL} helps your business, it is reasonable to ask that you help
+@strong{MySQL}. (Otherwise, if you ask us support questions, you are not
+only using for free something into which we've put a lot a work, you're
+asking us to provide free support, too.)
+@end itemize
+
+For circumstances under which a @strong{MySQL} license is required, you
+need a license per machine that runs the @code{mysqld} server. However,
+a multiple-CPU machine counts as a single machine, and there is no
+restriction on the number of @strong{MySQL} servers that run on one
+machine, or on the number of clients concurrently connected to a server
+running on that machine!
+
+If you have any questions as to whether or not a license is required for
+your particular use of @strong{MySQL}, please read this again and then
+contact us. @xref{Contact information}.
+
+If you require a @strong{MySQL} license, the easiest way to pay for it
+is to use the license form on @strong{MySQL}'s secure server at
+https://order.mysql.com/license.htmy. Other forms of payment are
+discussed in @ref{Payment information}.
+
+@cindex Copyright
+@node Copyright, Licensing examples, Licensing policy, Licensing and Support
+@section Copyrights used by MySQL
+
+@menu
+* Copyright changes:: Possible future copyright changes
+@end menu
+
+There are several different copyrights on the @strong{MySQL} distribution:
+
+@enumerate
+@item
+The @strong{MySQL}-specific source needed to build the
+@code{mysqlclient} library is licensed under the @code{LGPL} and
+programs in the @file{client} directory is GPL. Each file has a header
+that shows which copyright is used for that file.
+
+@item The client library and the (GNU @code{getopt}) library are covered
+by the ``GNU LIBRARY LIBRARY GENERAL PUBLIC LICENSE''.
+
+@item Some parts of the source (the @code{regexp} library) are covered
+by a Berkeley style copyright.
+
+@item All the source in the server and the (GNU @code{readline}) library
+is covered by the ``GNU GENERAL PUBLIC LICENSE''. @xref{GPL
+license}. This is also available as the file @file{COPYING} in the
+distributions.
+
+@end enumerate
+
+One goal with this is that the SQL client library should be free enough
+so that it is possible to add @strong{MySQL} support in commercial products
+without any license. So in this case we choose the LGPL license.
+
+This means that you can use @strong{MySQL} for free with any program that uses
+any of the free software licences. @strong{MySQL} is also free for any end user
+for his own/company usage.
+
+But if you use @strong{MySQL} for something important to you, you may
+want to help secure its development by purchasing licenses or a support
+contract, @ref{Support}.
+
+@node Copyright changes, , Copyright, Copyright
+@subsection Copyright changes
+
+The stable versions are of @strong{MySQL} are still using a more strict
+license. See the documatation for that version for more information.
+
+@node Licensing examples, Cost, Copyright, Licensing and Support
+@section Example licensing situations
+
+@menu
+* Products that use MySQL:: Selling products that use @strong{MySQL}
+* ISP:: ISP @strong{MySQL} services
+* Web server:: Running a web server using @strong{MySQL}.
+@end menu
+
+This section describes some situations illustrating whether or not you
+must license the @strong{MySQL} server. Generally these examples
+involve providing @strong{MySQL} as a integrated part of a product.
+
+Note that a single @strong{MySQL} license covers any number of CPUs and
+@code{mysqld} servers on a machine! It also has not limit on the number
+of clients that connect to one server in any way.
+
+@node Products that use MySQL, ISP, Licensing examples, Licensing examples
+@subsection Selling products that use @strong{MySQL}
+
+To determine whether or not you need a @strong{MySQL} license when
+selling your application, you should ask whether the proper functioning
+of your application is depentent on the use of @strong{MySQL} and
+whether you include the @strong{MySQL} server with your product. There
+are several cases to consider:
+
+@itemize @bullet
+@item
+Does your application require @strong{MySQL} to function properly?
+
+If your product requires @strong{MySQL}, you need a license for any
+machine that runs the @code{mysqld} server. For example, if you've
+designed your application around @strong{MySQL}, then you've really made
+a commercial product that requires the engine, so you need a license.
+
+If your application does not require @strong{MySQL}, you need not obtain
+a license. For example, if @strong{MySQL} just added some new optional
+features to your product (such as adding logging to a database if
+@strong{MySQL} is used rather than logging to a text file), it should
+fall within normal use, and a license would not be required.
+
+In other words, you need a license if you sell a product designed
+specifically for use with @strong{MySQL} or that requires the
+@strong{MySQL} server to function at all. This is true whether or not
+you provide @strong{MySQL} for your client as part of your product
+distribution.
+
+It also depends on what you're doing for the client. Do you plan to
+provide your client with detailed instructions on installing
+@strong{MySQL} with your software? Then your product may be contingent
+on the use of @strong{MySQL}; if so, you need to buy a license. If you
+are simply tying into a database that you expect already to have been
+installed by the time your software is purchased, then you probably
+don't need a license.
+
+@end itemize
+
+@node ISP, Web server, Products that use MySQL, Licensing examples
+@subsection ISP @strong{MySQL} services
+
+Internet Service Providers (ISPs) often host @strong{MySQL} servers for
+their customers. With the GPL license this does not require a license.
+
+On the other hand, we do encourage people to use ISP:s that has
+@strong{MySQL} support as this will give them the confidence that if
+they get some problem with their @strong{MySQL} installation, their ISP
+will be able to solve the problem for them (in some cases with the help
+from the @strong{MySQL} development team).
+
+All @code{ISPs} that wants to keep themself up to date should subscribe
+to our announce mailing list so that they can be aware of fatal issues
+that may be relevant for their @code{MySQL} installations.
+
+Note that if the @code{ISP} doesn't have a license for @code{MySQL},
+they should give their customers at least read access to the source of
+the @code{MySQL} installation so that their customer can verify that
+it's patched correctly.
+
+@node Web server, , ISP, Licensing examples
+@subsection Running a web server using @strong{MySQL}
+
+If you use @strong{MySQL} in conjunction with a web server on Unix, you
+don't have to pay for a license.
+
+This is true even if you run a commercial web server that uses
+@strong{MySQL}, because you are not selling an embedded @strong{MySQL}
+version yourself. However, in this case we would like you to purchase
+@strong{MySQL} support, because @strong{MySQL} is helping your
+enterprise.
+
+@cindex Costs, licensing and support
+@cindex Licensing costs
+@cindex Support costs
+@node Cost, Support, Licensing examples, Licensing and Support
+@section @strong{MySQL} licensing and support costs
+
+@menu
+* Payment information:: Payment information
+* Contact information:: Contact information
+@end menu
+
+Our current license prices are shown below. These prices are now under
+review because of the change to a GPL copyright. New prices and terms
+will be posted on the @strong{MySQL} web site
+@uref{http://www.mysql.com/} as soon as they are ready.
+
+All prices are in US Dollars. If you pay by credit card, the currency is
+EURO (European Union Euro) so the prices will differ slightly.
+
+@multitable @columnfractions .25 .2 .3
+@item @strong{Number of licenses} @tab @strong{Price per copy} @tab @strong{Total}
+@item 1 @tab US $200 @tab US $200
+@item 10 pack @tab US $150 @tab US $1500
+@item 50 pack @tab US $120 @tab US $6000
+@end multitable
+
+For high volume (OEM) purchases, the following prices apply:
+
+@multitable @columnfractions .25 .2 .3 .25
+@item @strong{Number of licenses} @tab @strong{Price per copy} @tab @strong{Minimum at one time} @tab @strong{Minimum payment}
+@item 100-999 @tab US $40 @tab 100 @tab US $4000
+@item 1000-2499 @tab US $25 @tab 200 @tab US $5000
+@item 2500-4999 @tab US $20 @tab 400 @tab US $8000
+@end multitable
+
+For OEM purchases, you must act as the middle-man for eventual problems
+or extension requests from your users. We also require that OEM
+customers have at least an extended email support contract. Note that
+OEM licenses only apply for products where the user doesn't have direct
+access to the @strong{MySQL} server (embedded system). In other words:
+The @strong{MySQL} server should only be used with the application
+that was supplied you.
+
+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.
+
+A full-price license is not a support agreement and includes very minimal
+support. This means that we try to answer any relevant question. If the
+answer is in the documentation, we will direct you to the appropriate
+section. If you have not purchased a license or support, we probably will 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. Descriptions of what each
+level of support includes are given in @ref{Support}. Costs for the various
+types of commercial support are shown below. Support level prices are in
+EURO (European Union Euro). One EURO is about 1.17 USD.
+
+@multitable @columnfractions .3 .3
+@item @strong{Type of support} @tab @strong{Cost per year}
+@item Basic email support @tab EURO 170
+@item Extended email support @tab EURO 1000
+@item Login support @tab EURO 2000
+@item Extended login support @tab EURO 5000
+@end multitable
+
+You may upgrade from any
+lower level of support to a higher level of support for the difference
+between the prices of the two support levels.
+
+@cindex Payment information
+@node Payment information, Contact information, Cost, Cost
+@subsection Payment information
+
+Currently we can take SWIFT payments, cheques or credit cards.
+
+Payment should be made to:
+@example
+Postgirot Bank AB
+105 06 STOCKHOLM, SWEDEN
+
+TCX DataKonsult AB
+BOX 6434
+11382 STOCKHOLM, SWEDEN
+
+SWIFT address: PGSI SESS
+Account number: 96 77 06 - 3
+@end example
+
+Specify: license and/or support and your name and email address.
+
+In Europe and Japan you can use EuroGiro (that should be less expensive) to the
+same account.
+
+If you want to pay by cheque, make it payable to ``MySQL Finland AB'' and
+mail it to the address below:
+
+@example
+TCX DataKonsult AB
+BOX 6434, Torsgatan 21
+11382 STOCKHOLM, SWEDEN
+@end example
+
+If you want to pay by credit card over the Internet, you can use
+@uref{https://order.mysql.com/license.htmy, MySQL AB's secure license form}.
+
+You can also print a copy of the license form, fill it in and send it by fax
+to:
+
++46-8-729 69 05
+
+If you want us to bill you, you can use the license form and write ``bill
+us'' in the comment field. You can also mail a message to
+@email{sales@@mysql.com} (@strong{not} @email{mysql@@lists.mysql.com}!)
+with your company information and ask us to bill you.
+
+@cindex Contact information
+@node Contact information, , Payment information, Cost
+@subsection Contact information
+
+For commercial licensing, or if you have any questions about any of the
+information in this section, please contact the @strong{MySQL} licensing
+team. The much preferred method is by E-Mail to
+@email{mysql-licensing@@mysql.com}. Fax is also possible but handling of
+these may take much longer (Fax +46-8-729 69 05).
+
+@example
+David Axmark
+Detron HB
+Kungsgatan 65 B
+753 21 UPPSALA
+SWEDEN
+Voice Phone +46-18-10 22 80
+(Timezone GMT+1. Swedish and English spoken)
+@end example
+
+@cindex Support, types
+@cindex Types of support
+@node Support, , Cost, Licensing and Support
+@section Types of commercial support
+
+@menu
+* Basic email support:: Basic email support
+* Extended email support:: Extended email support
+* Login support:: Login support
+* Extended login support:: Extended login support
+@end menu
+
+@node Basic email support, Extended email support, Support, Support
+@subsection Basic email support
+
+Basic email support is a very inexpensive support option and should be
+thought of more as a way to support our development of @strong{MySQL}
+than as a real support option. We at @strong{MySQL} do give a lot of free support
+in all the different @strong{MySQL} lists and the money we get from
+basic eamil support is largely used to make this possible.
+
+At this support level, the @strong{MySQL} mailing lists are the preferred
+means of communication. Questions normally should be mailed to the primary
+mailing list (@email{mysql@@lists.mysql.com}) or one of the other regular
+lists (for example, @email{win32@@lists.mysql.com} for Windows-related
+@strong{MySQL} questions), as someone else already may have experienced and
+solved the problem you have. @xref{Asking questions}.
+
+However, by purchasing basic email support, you also have access to the
+support address @email{mysql-support@@mysql.com}, which is not available
+as part of the minimal support that you get by purchasing a
+@strong{MySQL} license. This means that for especially critical
+questions, you can cross-post your message to
+@email{mysql-support@@mysql.com}. (If the message contains sensitive
+data, you should post only to @email{mysql-support@@mysql.com}.)
+
+@emph{REMEMBER!} to ALWAYS include your registration number and
+expiration date when you send a message to
+@email{mysql-support@@mysql.com}.
+
+Note that if you have encountered a critical repeatable bug and follow
+the rules outlined in the manual section of how to report bugs and send
+it to @email{bugs@@lists.mysql.com} we promise to try to fix this as
+soon as possible, independent of your support level! @xref{Bug reports}.
+
+Basic email support includes the following types of service:
+
+@itemize @bullet
+@item
+If your question is already answered in the manual, we will inform you of the
+correct section in which you can find the answer. If the answer is not in
+the manual, we will point you in the right direction to solve your problem.
+
+@item
+We guarantee a timely answer for your email messages. We can't guarantee
+that we can solve any problem, but at least you will receive an answer if we
+can contact you by email.
+
+@item
+We will help with unexpected problems when you install @strong{MySQL} from a
+binary distribution on supported platforms. This level of support does not
+cover installing @strong{MySQL} from a source distribution. ``Supported''
+platforms are those for which @strong{MySQL} is known to work.
+@xref{Which OS}.
+
+@item
+We will help you with bugs and missing features. Any bugs that are found are
+fixed for the next @strong{MySQL} release. If the bug is critical for
+you, 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.
+
+@item
+Your suggestions for the further development of @strong{MySQL} will be
+taken into consideration. By taking email support you have already
+helped the further development of @strong{MySQL}. If you want to have
+more input, upgrade to a higher level of support.
+
+@item
+If you want us to help optimize your system, you must upgrade to a
+higher level of support.
+
+@item
+@cindex @code{myisampack}
+We include a binary version of the @code{myisampack} packing tool for
+creating fast compressed read-only databases. The current server includes
+support for reading such databases but not the packing tool used to
+create them.
+@end itemize
+
+@node Extended email support, Login support, Basic email support, Support
+@subsection Extended email support
+
+Extended email support includes everything in basic email support with
+these additions:
+
+@itemize @bullet
+@item
+Your email will be dealt with before mail from basic email support users and
+non-registered users.
+
+@item
+Your suggestions for the further development of @strong{MySQL} will
+receive strong consideration. Simple extensions that suit the basic
+goals of @strong{MySQL} are implemented in a matter of days. By taking
+extended email support you have already helped the further development
+of @strong{MySQL}.
+
+@item
+Typical questions that are covered by extended email support are:
+
+@itemize @minus
+@item
+We will answer and (within reason) solve questions that relate to possible
+bugs in @strong{MySQL}. As soon as the bug is found and corrected, we
+will mail a patch for it.
+
+@item
+We will help with unexpected problems when you install @strong{MySQL} from a
+source or binary distribution on supported platforms.
+
+@item
+We will answer questions about missing features and offer hints how to work
+around them.
+
+@item
+We will provide hints on optimizing @code{mysqld} for your situation.
+@end itemize
+
+@item
+You are allowed to influence the priority of items on the @strong{MySQL}
+TODO. This will ensure that the features you really need will be implemented
+sooner than they might be otherwise.
+@end itemize
+
+@node Login support, Extended login support, Extended email support, Support
+@subsection Login support
+
+Login support includes everything in extended email support with
+these additions:
+
+@itemize @bullet
+@item
+Your email will be dealt with even before mail from extended email
+support users.
+
+@item
+Your suggestions for the further development of @strong{MySQL} will
+be taken into very high consideration. Realistic extensions that can be
+implemented in a couple of hours and that suit the basic goals of
+@strong{MySQL} will be implemented as soon as possible.
+
+@item
+If you have a very specific problem, we can try to log in on your system
+to solve the problem ``in place.''
+
+@item
+Like 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. @strong{MySQL} has proven itself very reliable, but anything is
+possible due to circumstances beyond our control (for example, if your system
+crashes or someone kills the server by executing a @code{kill -9} command).
+
+@item
+We will provide hints on optimizing your system and your queries.
+
+@item
+You are allowed to call a @strong{MySQL} developer (in moderation) and
+discuss your @strong{MySQL}-related problems.
+@end itemize
+
+@node Extended login support, , Login support, Support
+@subsection Extended login support
+
+Extended login support includes everything in login support with these
+additions:
+
+@itemize @bullet
+@item
+Your email has the highest possible priority.
+
+@item
+We will actively examine your system and help you optimize it and your
+queries. We may also optimize and/or extend @strong{MySQL} to better
+suit your needs.
+
+@item
+You may also request special extensions just for you. For example:
+@example
+mysql> select MY_FUNC(col1,col2) from table;
+@end example
+
+@item
+We will provide a binary distribution of all important @strong{MySQL}
+releases for your system, as long as we can get an account on a
+similar system. In the worst case, we may require access to your system
+to be able to create a binary distribution.
+
+@item
+If you can provide accommodations and pay for traveler fares, you can even
+get a @strong{MySQL} developer to visit you and offer you help with your
+troubles. Extended login support entitles you to one personal
+encounter per year, but we are as always very flexible towards our customers!
+@end itemize
+
+@node Installing, Compatibility, Licensing and Support, Top
+@chapter Installing MySQL
+
+@menu
+* Getting MySQL:: How to get @strong{MySQL}
+* Which OS:: Operating systems supported by @strong{MySQL}
+* Which version:: Which @strong{MySQL} version to use
+* Many versions:: How and when updates are released
+* Installation layouts:: Installation layouts
+* Installing binary:: Installing a @strong{MySQL} binary distribution
+* Installing source:: Installing a @strong{MySQL} source distribution
+* Compilation problems:: Problems compiling?
+* MIT-pthreads:: MIT-pthreads notes
+* Perl support:: Perl installation comments
+* Source install system issues:: System-specific issues
+* Win32:: Win32 notes
+* OS/2:: OS/2 notes
+* MySQL binaries::
+* Post-installation:: Post-installation setup and testing
+* Upgrade:: Is there anything special to do when upgrading/downgrading @strong{MySQL}?
+@end menu
+
+This chapter describes how to obtain and install @strong{MySQL}:
+
+@itemize @bullet
+@item
+For a list of sites from which you can obtain @strong{MySQL}, see
+@ref{Getting MySQL, , Getting @strong{MySQL}}.
+
+@item
+To see which platforms are supported, see @ref{Which OS}.
+
+@item
+Several versions of @strong{MySQL} are available, in both binary and
+source distributions. To determine which version and type of
+distribution you should use, see @ref{Many versions}.
+
+@item
+Installation instructions for binary and source distributions are described
+in @ref{Installing binary}, and @ref{Installing source}. Each set of
+instructions includes a section on system-specific problems you may run
+into.
+
+@item
+For post-installation procedures, see @ref{Post-installation}. These
+procedures apply whether you install @strong{MySQL} using a binary or
+source distribution.
+@end itemize
+
+@cindex Downloading
+@cindex @strong{MySQL} version
+@cindex Version, latest
+@cindex Getting @strong{MySQL}
+@node Getting MySQL, Which OS, Installing, Installing
+@section How to get MySQL
+
+Check the @uref{http://www.mysql.com/, @strong{MySQL} home page} for
+information about the current version and for downloading instructions.
+
+If you have problems downloading from our main site, try using on of the
+mirrors listed below.
+
+Please report bad or out of date mirrors to @email{webmaster@@mysql.com}.
+
+@c START_OF_MIRROR_LISTING
+
+@strong{Europe:}
+
+@itemize @bullet
+@item
+@c EMAIL: sl@iuinfo.tuwien.ac.at (Tony Sprinzl)
+@image{Flags/austria} Austria [Univ. of Technology/Vienna] @
+@uref{http://gd.tuwien.ac.at/db/mysql/, WWW}
+@uref{ftp://gd.tuwien.ac.at/db/mysql/, FTP}
+@item
+@c EMAIL: delian@naturella.com (Delian Delchev)
+@image{Flags/bulgaria} Bulgaria [Naturella] @
+@uref{http://archive.nat.bg/pub/mirror/mysql/, WWW}
+@uref{ftp://ftp.ntrl.net/pub/mirror/mysql/, FTP}
+@item
+@c Added: 990614
+@c EMAIL: vuksan@veus.hr (Vladimir Vuksan)
+@image{Flags/croatia} Croatia [HULK] @
+@uref{http://ftp.linux.hr/pub/mysql/, WWW}
+@uref{ftp://ftp.linux.hr/pub/mysql/, FTP}
+@item
+@c Added: 990614
+@c EMAIL: kas@informatics.muni.cz (Jan Kasprzak)
+@image{Flags/czech-republic} Czech Republic [Masaryk University in Brno] @
+@uref{http://mysql.linux.cz/index.html, WWW}
+@uref{ftp://ftp.fi.muni.cz/pub/mysql/, FTP}
+@item
+@c Added: 990920
+@c EMAIL: <radek@sopik.cz> (Radek Libovicky)
+@image{Flags/czech-republic} Czech Republic [www.sopik.cz] @
+@uref{http://www.mysql.cz/, WWW}
+@item
+@c Added: 000418
+@c EMAIL: <feela@ipex.cz> (Ondrej Feela Filip)
+@image{Flags/czech-republic} Czech Republic [www.gin.cz] @
+@uref{http://mysql.gin.cz/, WWW}
+@uref{ftp://ftp.gin.cz/pub/MIRRORS/www.mysql.com/, FTP}
+@item
+@c removed 991020 (no DNS entry). New name 991026. Added 991121
+@c Statistics at http://mirror.borsen.dk/
+@c EMAIL: mirrorman@borsen.dk (Michael Kyed)
+@image{Flags/denmark} Denmark [Borsen] @
+@uref{ http://mysql.borsen.dk/, WWW}
+@item
+@c EMAIL: mkp@socsci.auc.dk (Martin Kasper Petersen)
+@image{Flags/denmark} Denmark [SunSITE] @
+@uref{http://SunSITE.auc.dk/mysql/, WWW}
+@uref{ftp://SunSITE.auc.dk/pub/databases/mysql/, FTP}
+@c @item
+@c Tõnu does not work there anymore :-) 990720
+@c EMAIL: tonu@tradenet.ee (Tõnu Samuel)
+@c @image{Flags/estonia} Estonia [Tradenet] @
+@c @uref{http://mysql.tradenet.ee, WWW}
+@item
+@c EMAIL: tonu@spamm.ee (Tõnu Samuel)
+@image{Flags/estonia} Estonia [OKinteractive] @
+@uref{http://mysql.mirror.ok.ee, WWW}
+@item
+@c Changed 990531
+@c EMAIL: Steeve.Devergne@minet.net (Steeve Devergne)
+@image{Flags/france} France [minet] @
+@uref{http://www.minet.net/devel/mysql/, WWW}
+@item
+@c EMAIL: Jaakko.Hyvatti@eunet.fi
+@image{Flags/finland} Finland [EUnet] @
+@uref{http://mysql.eunet.fi/, WWW}
+@item
+@c Added 990829
+@c EMAIL: tomi.hakala@clinet.fi (Tomi Hakala)
+@image{Flags/finland} Finland [clinet] @
+@uref{ftp://ftp.clinet.fi/mirrors/ftp.mysql.org/pub/mysql/, FTP}
+@item
+@c Added 981208
+@c EMAIL: noel@uni-bonn.de (Noel Koethe)
+@image{Flags/germany} Germany [Bonn University, Bonn] @
+@uref{http://www.wipol.uni-bonn.de/MySQL//, WWW}
+@uref{ftp://ftp.wipol.uni-bonn.de/pub/mirror/MySQL/, FTP}
+@item
+@c EMAIL: th@rz.fh-wolfenbuettel.de (Thorsten Ludewig)
+@image{Flags/germany} Germany [Wolfenbuettel] @
+@uref{http://www.fh-wolfenbuettel.de/ftp/pub/database/mysql/, WWW}
+@uref{ftp://ftp.fh-wolfenbuettel.de/pub/database/mysql/, FTP}
+@item
+@c Ok 980114. Removed 981208 (down > 3 days) ok 981214
+@c EMAIL: straub@gks.de (Hans-Peter Straub)
+@image{Flags/germany} Germany [Staufen] @
+@uref{http://mysql.staufen.de/, WWW}
+@item
+@c Added 990614
+@c EMAIL: thomas.rohde@ecrc.de (Thomas Rohde)
+@image{Flags/germany} Germany [Cable & Wireless] @
+@uref{ftp://ftp.ecrc.net/pub/database/mysql/, FTP}
+@item
+@c Added 981208
+@c EMAIL: christias@noc.ntua.gr (Panagiotis Christias)
+@image{Flags/greece} Greece [NTUA, Athens] @
+@uref{http://www.ntua.gr/mysql/, WWW}
+@uref{ftp://ftp.ntua.gr/pub/databases/mysql/, FTP}
+@c @item
+@c File not found 990730
+@c EMAIL: torlasz@xenia.sote.hu (Laszlo L. Tornoc)
+@c @image{Flags/hungary} Hungary [Xenia] @
+@c @uref{http://xenia.sote.hu/ftp/mirrors/www.mysql.com/, WWW}
+@c @uref{ftp://xenia.sote.hu/pub/mirrors/www.mysql.com/,FTP}
+@item
+@c EMAIL: mirrors@gm.is (Tomas Edwardsson)
+@image{Flags/iceland} Island [GM] @
+@uref{http://mysql.gm.is/, WWW}
+@uref{ftp://ftp.gm.is/pub/mysql, WWW}
+@c @item
+@c Out of date 990906
+@c EMAIL: bourbon@netvision.net.il (Zeev Suraski)
+@c @image{Flags/israel} Israel [Netvision] @
+@c @uref{http://mysql.netvision.net.il/, WWW}
+@c @item
+@c Not working 99.03.06
+@c EMAIL: maruzz@matrice.it (Giovanni Maruzzelli)
+@c @image{Flags/italy} Italy [Matrice] @
+@c @uref{http://www.matrice.it/risorse/mysql/, WWW}
+@item
+@c EMAIL: irena@yacc.it
+@image{Flags/italy} Italy [Teta Srl] @
+@uref{http://www.teta.it/mysql/, WWW}
+@item
+@c Added 991121
+@c EMAIL: nick@iol.ie (Nick Hilliard)
+@image{Flags/ireland} Ireland [Ireland On-Line/Dublin] @
+@uref{http://mysql.iol.ie, WWW}
+@uref{ftp://ftp.iol.ie/pub/mysql, FTP}
+@item
+@c EMAIL: W.Sylwestrzak@icm.edu.pl (Wojtek Sylwestrzak)
+@c mirroring nightly at 05:25
+@image{Flags/poland} Poland [Sunsite] @
+@uref{http://sunsite.icm.edu.pl/mysql/, WWW}
+@uref{ftp://sunsite.icm.edu.pl/pub/unix/mysql/, FTP}
+@c @item
+@c EMAIL: melo@co.telenet.pt (Pedro Melo)
+@c Temp out of service (email from Pedro)
+@c @image{Flags/portugal} Portugal [IP] @
+@c @uref{http://mysql.ip.pt, WWW}
+@item
+@c EMAIL: Equipa de suporte do Leirianet <support@leirianet.pt>
+@image{Flags/portugal} Portugal [lerianet] @
+@uref{http://mysql.leirianet.pt, WWW}
+@uref{ftp://ftp.leirianet.pt/pub/mysql/,FTP}
+@item
+@c EMAIL: kuzmin@dn.ru (Roma Kuzmin)
+@image{Flags/russia} Russia [DirectNet] @
+@uref{http://mysql.directnet.ru, WWW}
+@uref{ftp://ftp.dn.ru/pub/MySQL, FTP}
+@c @item
+@c down 990113
+@c EMAIL: nikkic@cityline.ru (Nikki Chumakov)
+@c @image{Flags/russia} Russia [Cityline] @
+@c @uref{ftp://mysql.cityline.ru/pub/mysql, FTP}
+@c @uref{http://mysql.cityline.ru, WWW}
+@c EMAIL: bar@izhcom.ru (Alexander I Barkov)
+@item
+@image{Flags/russia} Russia [IZHCOM] @
+@uref{http://mysql.udm.net/, WWW}
+@uref{ftp://ftp.izhcom.ru/pub/mysql/,FTP}
+@item
+@c Added 990507
+@c EMAIL: demon@gpad.ac.ru (Dima Sivachenko)
+@image{Flags/russia} Russia [Scientific Center/Chernogolovka] @
+@uref{ftp://ftp.chg.ru/pub/databases/mysql/, FTP}
+@item
+@c EMAIL: sebi@dnttm.ro (Sebastian DEAC)
+@image{Flags/romania} Romania [Timisoara] @
+@uref{http://www.dnttm.ro/mysql, WWW}
+@uref{ftp://ftp.dnttm.ro/pub/mysql, FTP}
+@item
+@c EMAIL: tim@lbi.ro (Bogdan Surdu)
+@image{Flags/romania} Romania [Bucharest] @
+@uref{http://www.lbi.ro/MySQL, WWW}
+@uref{ftp://ftp.lbi.ro/mirrors/ftp.tcx.se, FTP}
+
+@c @item
+@c Removed 20000521 because there is no mirror here.
+@c EMAIL: jips@masterd.es (Juan Ignacio Pérez Sacristán)
+@c @image{Flags/spain} Spain [MasterD]
+@c @uref{http://mysql.masterd.es, WWW}
+
+@item
+@c EMAIL: Patrik.Karen@sdi.slu.se (Patrik Karen)
+@c ftp -> remove old files
+@image{Flags/sweden} Sweden [Sunet] @
+@uref{http://ftp.sunet.se/pub/unix/databases/relational/mysql/, WWW}
+@uref{ftp://ftp.sunet.se/pub/unix/databases/relational/mysql/, FTP}
+
+@item
+@c EMAIL: archive@sunsite.cnlab-switch.ch (Thomas Lenggenhager)
+@image{Flags/switzerland} Switzerland [Sunsite] @
+@uref{http://sunsite.cnlab-switch.ch/ftp/mirror/mysql/, WWW}
+@uref{ftp://sunsite.cnlab-switch.ch/mirror/mysql/, FTP}
+
+@c @item
+@c @c simon@oyster.co.uk (Simon Gornall)
+@c @image{Flags/great-britain} UK [Oyster/UK] @
+@c @uref{ftp://ftp.oyster.co.uk/pub/mysql, FTP}
+
+@item
+@c gareth@omnipotent.net (Gareth Watts)
+@image{Flags/great-britain} UK [Omnipotent/UK] @
+@uref{http://mysql.omnipotent.net/, WWW}
+@uref{ftp://mysql.omnipotent.net/, FTP}
+
+@item
+@c keet@mordor.plig.net (Christiaan Keet)
+@image{Flags/great-britain} UK [PLiG/UK] @
+@uref{http://ftp.plig.org/pub/mysql/, WWW}
+@uref{ftp://ftp.plig.org/pub/mysql/, FTP}
+@c @item
+@c unknown
+@c @image{Flags/great-britain} UK [MicroMuse] @
+@c @uref{ftp://ftp.micromuse.co.uk/pub/packages/unix/databases/mysql/, FTP}
+
+@item
+@c lmjm@icparc.ic.ac.uk (Lee McLoughlin)
+@image{Flags/great-britain} UK [SunSITE] @
+@uref{http://sunsite.org.uk/packages/mysql/, WWW}
+@uref{ftp://sunsite.org.uk/packages/mysql/, FTP}
+
+@item
+@c sander@paco.net (Alexander Ivanov)
+@image{Flags/ukraine} Ukraine [PACO] @
+@uref{http://mysql.paco.net.ua, WWW}
+@uref{ftp://mysql.paco.net.ua/, FTP}
+
+@end itemize
+
+@strong{North America:}
+
+@itemize @bullet
+@c @item
+@c Not ok 990101 (only to 981007)
+@c EMAIL: sysop@polarcom.com (Seamus Venasse)
+@c @image{Flags/canada} Canada [Polaris Computing] @
+@c @uref{http://mysql.polaris.ca/, WWW}
+
+@item
+@c Ok 980109
+@c EMAIL: wojtek@tryc.on.ca (Wojtjeck Tryc)
+@image{Flags/canada} Canada [Tryc] @
+@uref{http://web.tryc.on.ca/mysql/, WWW}
+
+@item
+@c not updated 990218. Added again 990918
+@c EMAIL: rhooper@cyberus.ca (Roy Hooper)
+@image{Flags/canada} Canada [Cyberus] @
+@uref{http://mysql.cyberus.ca/, WWW}
+@uref{ftp://mysql.cyberus.ca/, FTP}
+
+@item
+@c EMAIL: mleber@he.net (Mike Leber)
+@c Added 980312
+@image{Flags/usa} USA [Hurricane Electric/San Jose] @
+@uref{http://mysql.he.net, WWW}
+
+@item
+@c EMAIL: meltzer@icsnet.com (Jeffrey Meltzer)
+@c Added 000108
+@image{Flags/usa} USA [Meltzer/New York State] @
+@uref{ftp://ftp.meltzer.org/pub/mysql/, FTP}
+
+@c @item
+@c No such directory 990830
+@c EMAIL: tps@users.buoy.com (Tim Sailer)
+@c @image{Flags/usa} USA [Buoy/New York] @
+@c @uref{http://www.buoy.com/mysql/, WWW}
+
+@c @item
+@c EMAIL: db@hpnc.com (Douglas Bowyer)
+@c Added 980107, removed 981124 because of 'file not found'
+@c @image{Flags/usa} USA [Hypernet Communications/Dallas] @
+@c @uref{http://epsilon.hpnc.com/mysql, WWW}
+
+@c @item @c **********************************
+@c Not updated 980106
+@c EX: twh@iquest.net (Thomas Holt) who no longer works there
+@c @image{Flags/usa} USA [IQuest/Indiana] @
+@c @uref{http://mirrors.iquest.net/mysql/, WWW}
+
+@c @item @c **********************************
+@c Only a partial mirror so we exclude it from the list
+@c EX: lindberg@id.wustl.edu (Fred Lindberg)
+@c @image{Flags/usa} USA [Washington University/St. Louis] @
+@c @uref{ftp://ftp.id.wustl.edu/pub/database/mysql/, FTP}
+
+@c removed 991111 -> no answer
+@c @item
+@c EMAIL: andrew@netcasting.net (Andrew Sawyers)
+@c @image{Flags/usa} USA [Netcasting/West Coast] @
+@c @uref{ftp://ftp.netcasting.net/pub/mysql/, FTP}
+
+@c @item
+@c No mirror! 980809 David
+@c EMAIL: savages@savages.com (Shaun Savage)
+@c @image{Flags/usa} USA [Savages/Oregon] @
+@c @uref{http://mysql.savages.com, WWW}
+
+@item
+@c EMAIL: tcobb@staff.circle.net (Troy Cobb)
+@image{Flags/usa} USA [Circle Net/North Carolina] @
+@uref{http://www.mysql.net, WWW}
+
+@item
+@c EMAIL: paul@gina.net (Paul Vining)
+@c mirrors ftp.sunet.se
+@image{Flags/usa} USA [Gina net/Florida] @
+@uref{http://www.gina.net/mysql/, WWW}
+
+@c Out of date 2000-01-08 (Not updated since 1999-10)
+@c @item
+@c EMAIL: wswanson@pingzero.net (Wylie Swanson)
+@c mirrors mysql.org
+@c @image{Flags/usa} USA [pingzero/Los Angeles] @
+@c @uref{http://mysql.pingzero.net/, WWW}
+
+@item
+@c EMAIL: ftpkeeper@mirror.sit.wisc.edu
+@image{Flags/usa} USA [Wisconsin University/Wisconsin] @
+@uref{http://mirror.sit.wisc.edu/mysql/, WWW}
+@uref{ftp://mirror.sit.wisc.edu/mirrors/mysql/, FTP}
+
+@item
+@c EMAIL: ftp-admin@digex.net
+@image{Flags/usa} USA [DIGEX] @
+@uref{ftp://ftp.digex.net/pub/packages/database/mysql/, FTP}
+
+@item
+@c EMAIL: andrew.sawyers@thelinuxstore.com
+@image{Flags/usa} USA [LinuxWired/Scottsdale, AZ] @
+@uref{http://mysql.linuxwired.net/, WWW}
+@uref{ftp://ftp.linuxwired.net/pub/mirrors/mysql/, FTP}
+
+@end itemize
+
+@strong{South America:}
+
+@itemize @bullet
+@item
+@c EMAIL: gaiser@matrix.com.br (Roberto Gaiser)
+@image{Flags/brazil} Brazil [Matrix] @
+@uref{http://mysql.matrix.com.br, WWW}
+@item
+@c jpabuyer@vision.cl
+@image{Flags/chile} Chile [Vision] @
+@uref{http://mysql.vision.cl/, WWW}
+
+@c @item
+@c Removed 990730
+@c @c EMAIL: dan@amerikanclaris.com (Danilo Lotina F.)
+@c @image{Flags/chile} Chile [Amerikanclaris] @
+@c @uref{http://www.labs.amerikanclaris.cl/mysql, WWW}
+@c @uref{ftp://ftp.amerikanclaris.cl/pub/mysql, FTP}
+@end itemize
+
+@strong{Asia:}
+
+@itemize @bullet
+@item
+@c EMAIL: mirnshi@netchina.com.cn (Meng Lingbo)
+@image{Flags/china} China [Freecode] @
+@uref{http://mysql.freecode.com.cn, WWW}
+
+@item
+@c EMAIL: Vincent_Fong@innovator.com.hk (Vincent Fong)
+@image{Flags/china} China [Hong Kong] @
+@uref{http://mysql.islnet.net, WWW}
+
+@item
+@c EMAIL: george@netfirm.net (Hongsheng Zhu)
+@image{Flags/china} China [Netfirm] @
+@uref{http://mysql.netfirm.net, WWW}
+
+@item
+@c EMAIL: ahmlhs@nmsvr.chosun.com (Ho-sun Lee)
+@image{Flags/south-korea} Korea [KREONet] @
+@uref{http://linux.kreonet.re.kr/mysql/, WWW}
+
+@c @item
+@c ftp -> remove old files
+@c EX: ahmlhs@nmsvr.chosun.com (Ho-sun Lee)
+@c @image{Flags/south-korea} Korea [KREONet] @
+@c @uref{ftp://linux.kreonet.re.kr/pub/tools/db/mysql/, FTP}
+
+@item
+@c Ok 980805
+@c EMAIL: takeshi@SoftAgency.co.jp
+@image{Flags/japan} Japan [Soft Agency] @
+@uref{http://www.softagency.co.jp/MySQL, WWW}
+
+@c @item
+@c Ok 980109 Removed 990730
+@c EMAIL: satoshi@HappySize.co.jp (Satoshi TATSUOKA)
+@c @image{Flags/japan} Japan [HappySize] @
+@c @uref{http://www.happysize.co.jp/mysql/, WWW}
+@c @uref{ftp://ftp.happysize.co.jp/pub/mysql/, FTP}
+
+@item
+@c Ok 981204
+@c EMAIL: hiroyuki@nucba.ac.jp (hiroyuki kurimoto)
+@image{Flags/japan} Japan [Nagoya Syouka University] @
+@uref{http://mirror.nucba.ac.jp/mirror/mysql, WWW}
+@uref{ftp://mirror.nucba.ac.jp/mirror/mysql, FTP}
+
+@c @item
+@c Removed 990308
+@c EMAIL: terence@com5.net (Terence Chan)
+@c @image{Flags/singapore} Singapore [Com5 Productions] @
+@c @uref{http://mysql.com5.net, WWW}
+@c @uref{ftp://ftp.com5.net/pub/mysql, FTP}
+
+@item
+@c EMAIL: csy@hjc.edu.sg
+@image{Flags/singapore} Singapore [HJC] @
+@uref{http://mysql.hjc.edu.sg, WWW}
+@uref{ftp://ftp.hjc.edu.sg/mysql, FTP}
+
+@item
+@c 991118: Removed because a user complained about that the page contains
+@c nothing about MySQL. 991119: Added again because it is a mirror again
+@c EMAIL: dean@ht.net.tw (Dean Lin)
+@image{Flags/taiwan} Taiwan [HT] @
+@uref{http://mysql.ht.net.tw, WWW}
+
+@item
+@c EMAIL: linda@ttn.com.tw (Linda Hu)
+@image{Flags/taiwan} Taiwan [TTN] @
+@uref{http://mysql.ttn.net, WWW}
+
+@c @item
+@c Ok 980321 No connect -> removed 990730
+@c EMAIL: tby@ccca.nctu.edu.tw (Bao-Yi Tuang)
+@c @image{Flags/taiwan} Taiwan [NCTU] @
+@c @uref{http://mysql.taconet.com.tw, WWW}
+@c @item
+@c Out of date 990905 (~2 months)
+@c @item @c **********************************
+@c Error 980106
+@c EX: WolfySu@acer.net (Wolfy Su)
+@c @image{Flags/taiwan} Taiwan [Acer] @
+@c @uref{http://mysql.acer.net/, WWW}
+@c @item @c **********************************
+@c files to delete
+@c EX: service@wownet.net
+@c @image{Flags/taiwan} Taiwan [Wownet] @
+@c @uref{ftp://ftp.wownet.net/mysql/, FTP}
+@c @item @c **********************************
+@c No conntact 980106
+@c EX: serge@oneway.net
+@c @image{Flags/taiwan} Taiwan [Oneway] @
+@c @uref{ftp://ftp.oneway.com.tw/pub/mysql/, FTP}
+@end itemize
+
+@strong{Australia:}
+
+@itemize @bullet
+@item
+@c Added 980610
+@c EMAIL: jason@dstc.edu.au (Jason Andrade)
+@image{Flags/australia} Australia [AARNet/Queensland] @
+@uref{http://mirror.aarnet.edu.au/mysql, WWW}
+@uref{ftp://mirror.aarnet.edu.au/pub/mysql, FTP}
+
+@c @item
+@c Added 980805. Removed 000102 'no such directory'
+@c EMAIL: sdd@ntccc.tas.gov.au (Scott Donovan)
+@c @image{Flags/australia} Australia [Tas] @
+@c @uref{http://ftp.tas.gov.au/mysql, WWW}
+@c @uref{ftp://ftp.tas.gov.au/pub/mysql, FTP}
+
+@item
+@c Ok 980623
+@c EMAIL: samh@bluep.com (Sam Hadzajlic)
+@image{Flags/australia} Australia [Blue Planet/Melbourne] @
+@uref{http://mysql.bluep.com/, WWW}
+@c removed because ftp was not working 990729 & 30
+@c @uref{ftp://mysql.bluep.com/pub/mirror1/mysql/, FTP}
+
+@item
+@c Added 990531
+@c EMAIL: gavin@itworks.com.au (Gavin Cameron)
+@image{Flags/australia} Australia [ITworks Consulting/Victoria] @
+@uref{http://mysql.itworks.com.au, WWW}
+
+@c @item
+@c 980610 Only the toplevel dir!
+@c EMAIL: lucifer@maths.uq.edu.au (David Conran)
+@c @image{Flags/australia} Australia FTP @
+@c @uref{ftp://ftp.sage-au.org.au/pub/database/mysql, [Sage]}
+@end itemize
+
+@strong{Africa:}
+
+@itemize @bullet
+
+@item
+@c Ok 981010
+@c EMAIL: nick@mweb.com (Nick Rosenberg)
+@image{Flags/south-africa1} South-Africa [Mweb/] @
+@uref{http://www.mysql.mweb.co.za, WWW}
+
+@item
+@c Ok 981010
+@c EMAIL: oskar@is.co.za (Oskar Pearson)
+@image{Flags/south-africa1} South-Africa [The Internet Solution/Johannesburg] @
+@uref{ftp://ftp.is.co.za/linux/mysql/, FTP}
+
+@end itemize
+
+@c END_OF_MIRROR_LISTING
+
+@node Which OS, Which version, Getting MySQL, Installing
+@section Operating systems supported by MySQL
+
+We use GNU Autoconf so it is possible to port @strong{MySQL} to all modern
+systems with working Posix threads and a C++ compiler. (To compile only the
+client code, a C++ compiler is required but not threads.) We use and develop
+the software ourselves primarily on Sun Solaris (versions 2.5 & 2.6) and to a
+lesser extent on RedHat Linux 5.0.
+
+@strong{MySQL} has been reported to compile sucessfully on the following
+operating system/thread package combinations. Note that for many operating
+systems, the native thread support works only in the latest versions.
+
+@itemize @bullet
+@item
+AIX 4.x with native threads. @xref{IBM-AIX}.
+@item
+BSDI 2.x with the included MIT-pthreads package. @xref{BSDI}.
+@item
+BSDI 3.0, 3.1 and 4.x with native threads. @xref{BSDI}.
+@item
+DEC UNIX 4.x with native threads. @xref{Alpha-DEC-Unix}.
+@item
+FreeBSD 2.x with the included MIT-pthreads package. @xref{FreeBSD}.
+@item
+FreeBSD 3.x with native threads. @xref{BSDI}.
+@item
+HP-UX 10.20 with the included MIT-pthreads package. @xref{HP-UX 10.20}.
+@item
+HP-UX 11.x with the native threads. @xref{HP-UX 11.x}.
+@item
+Linux 2.0+ with LinuxThreads 0.7.1 or @code{glibc} 2.0.7 . @xref{Linux}.
+@item
+MacOS X Server. @xref{MacOSX}.
+@item
+NetBSD 1.3/1.4 Intel and NetBSD 1.3 Alpha (Requires GNU make). @xref{NetBSD}.
+@item
+OpenBSD > 2.5 with native therads. OpenBSD < 2.5 with the included
+MIT-pthreads package. @xref{OpenBSD}.
+@item
+OS/2 Warp 3, FixPack 29 and OS/2 Warp 4, FixPack 4. @xref{OS/2}.
+@item
+SGI Irix 6.x with native threads. @xref{SGI-Irix}.
+@item
+Solaris 2.5 and above with native threads on SPARC and x86. @xref{Solaris}.
+@item
+SunOS 4.x with the included MIT-pthreads package. @xref{Solaris}.
+@item
+SCO OpenServer with a recent port of the FSU Pthreads package. @xref{SCO}.
+@item
+SCO UnixWare 7.0.1. @xref{SCO Unixware}.
+@item
+Tru64 Unix
+@item
+Win95, Win98, NT and Win2000. @xref{Win32}.
+@end itemize
+
+@cindex @strong{MySQL} binary distribution
+@cindex @strong{MySQL} source distribution
+@cindex Release numbers
+@cindex Version, choosing
+@cindex Choosing version
+@node Which version, Many versions, Which OS, Installing
+@section Which MySQL version to use
+
+The first decision to make is whether you want to use the latest development
+release or the last stable release:
+
+@itemize @bullet
+@item
+Normally, if you are beginning to use @strong{MySQL} for the first time
+or trying to port it to some system for which there is no binary
+distribution, we recommend going with the development release (currently
+@value{mysql_version}. This is because there are usually no really
+serious bugs in the development release, and you can easily test it on
+your machine with the @code{crash-me} and benchmark tests.
+@xref{Benchmarks}. Note that all @strong{MySQL} releases are
+checked with the @strong{MySQL} benchmarks and an extensive test suite
+before each release.
+
+@item
+Otherwise, if you are running an old system and want to upgrade, but
+don't want to take chances with the development version, you should
+upgrade to the latest in the same branch you are using (where only the
+last version number is newer than yours). We have tried to fix only
+fatal bugs and make small, relatively safe changes to that version.
+@end itemize
+
+The second decision to make is whether you want to use a source distribution or
+a binary distribution:
+
+@itemize @bullet
+@item
+If you want to run @strong{MySQL} on a platform for which a current binary
+distribution exists, use that. Generally, it will be easier to install
+than a source distribution.
+
+@item
+If you want to read (and/or modify) the C and C++ code that makes up
+@strong{MySQL}, you should get a source distribution. The source code is
+always the ultimate manual. Source distributions also contain more
+tests and examples than binary distributions.
+@end itemize
+
+The @strong{MySQL} naming scheme uses release numbers that consist of three
+numbers and a suffix. For example, a release name like
+@code{mysql-3.21.17-beta} is interpreted like this:
+
+@itemize @bullet
+@item
+The first number (@code{3}) describes the file format. All
+version 3 releases have the same file format. When a version 4 appears, every
+table will have to be converted to the new format (nice tools for this will
+be included, of course).
+
+@item
+The second number (@code{21}) is the release level. Normally there are two to
+choose from. One is the release/stable branch (currently @code{22}) and the
+other is the development branch (currently @code{23}) . Normally both are
+stable, but the development version may have quirks, missing documentation on
+new features or may fail to compile on some systems.
+
+@item
+The third number (@code{17}) is the version number within the
+release level. This is incremented for each new distribution. Usually you
+want the latest version for the release level you have choosen.
+
+@item
+The suffix (@code{beta}) indicates the stability level of the release.
+The possible suffixes are:
+
+@itemize @minus
+@item @code{alpha} indicates that the release contains some large section of
+new code that hasn't been 100% tested. Known bugs (usually there are none)
+should be documented in the News section. @xref{News}. There are also new
+commands and extensions in most alpha releases. Active development that
+may involve major code changes can occur on an alpha release, but everything
+will be tested before doing a release. There should be no known bugs in any
+@code{MySQL} release.
+
+@item
+@code{beta} means that all new code has been tested. No major new
+features that could cause corruption on old code are added. There should
+be no known bugs. A version changes from alpha to beta when there
+haven't been any reported fatal bugs within an alpha version for at least
+a month and we don't plan to add any features that could make any old command
+more unreliable.
+
+@item
+@code{gamma} is a beta that has been around a while and seems to work fine.
+Only minor fixes are added. This is what many other companies call a release.
+
+@item
+If there is no suffix, it means that the version has been run for a
+while at many different sites with no reports of bugs other than
+platform-specific bugs. Only critical bug fixes are applied to the
+release. This is what we call a stable release.
+@end itemize
+@end itemize
+
+All versions of @strong{MySQL} are run through our standard tests and
+benchmarks to ensure that they are relatively safe to use. Because the
+standard tests are extended over time to check for all previously found bugs,
+the test suite keeps getting better.
+
+Note that all releases have been tested at least with:
+
+@table @asis
+@item An internal test suite
+This is part of a production system for a customer. It has many tables with
+hundreds of megabytes of data.
+
+@item The @strong{MySQL} benchmark suite
+This runs a range of common queries. It is also a test to see whether the
+latest batch of optimizations actually made the code faster.
+@xref{Benchmarks}.
+
+@item The @code{crash-me} test
+This tries to determine what features the database supports and what its
+capabilities and limitations are.
+@xref{Benchmarks}.
+@end table
+
+Another test is that we use the newest @strong{MySQL} version in our internal
+production environment, on at least one machine. We have more than 100
+gigabytes of data to work with.
+
+@node Many versions, Installation layouts, Which version, Installing
+@section How and when updates are released
+
+@strong{MySQL} is evolving quite rapidly here at MySQL AB and we want
+to share this with other @strong{MySQL} users. We try to make a release
+when we have very useful features 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 of what our licensed users want to have and
+we especially take note of 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. @xref{News}.
+
+We use the following policy when updating @strong{MySQL}:
+
+@itemize @bullet
+@item
+For each minor update, the last number in the version string is incremented.
+When there are major new features or minor incompatibilities with previous
+versions, the second number in the version string is incremented. When the
+file format changes, the first number is increased.
+
+@item
+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.
+
+@item
+Working releases are meant to appear about every 1-8 weeks.
+
+@item
+Binary distributions for some platforms will be made by us for major releases.
+Other people may make binary distributions for other systems but probably
+less frequently.
+
+@item
+We usually make patches available as soon as we have located and fixed
+small bugs.
+
+@item
+For non-critical but annoying bugs, we will make patches available if they
+are sent to us. Otherwise we will combine many of them into a larger
+patch.
+
+@item
+If there is, by any chance, a fatal bug in a release we will make a new
+release as soon as possible. We would like other companies to do this,
+too. :)
+@end itemize
+
+The current stable release is 3.22; We have already moved active
+development to 3.23. 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 frozen'' means that we may
+add small things that ``almost surely will not affect anything that's
+already working''.
+
+@node Installation layouts, Installing binary, Many versions, Installing
+@section Installation layouts
+
+This section describes the default layout of the directories created by
+installing binary and source distributions.
+
+A binary distribution is installed by unpacking it at the installation
+location you choose (typically @file{/usr/local/mysql}) and creates the
+following directories in that location:
+
+@multitable @columnfractions .3 .7
+@item @strong{Directory} @tab @strong{Contents of directory}
+@item @file{bin} @tab Client programs and the @code{mysqld} server
+@item @file{data} @tab Log files, databases
+@item @file{include} @tab Include (header) files
+@item @file{lib} @tab Libraries
+@item @file{scripts} @tab @code{mysql_install_db}
+@item @file{share/mysql} @tab Error message files
+@item @file{sql-bench} @tab Benchmarks
+@end multitable
+
+A source distribution is installed after you configure and compile it. By
+default, the installation step installs files under @file{/usr/local}, in the
+following subdirectories:
+
+@multitable @columnfractions .3 .7
+@item @strong{Directory} @tab @strong{Contents of directory}
+@item @file{bin} @tab Client programs and scripts
+@item @file{include/mysql} @tab Include (header) files
+@item @file{info} @tab Documentation in Info format
+@item @file{lib/mysql} @tab Libraries
+@item @file{libexec} @tab The @code{mysqld} server
+@item @file{share/mysql} @tab Error message files
+@item @file{sql-bench} @tab Benchmarks and @code{crash-me} test
+@item @file{var} @tab Databases and log files.
+@end multitable
+
+Within an installation directory, the layout of a source installation differs
+from that of a binary installation in the following ways:
+
+@itemize @bullet
+@item
+The @code{mysqld} server is installed in the @file{libexec}
+directory rather than in the @file{bin} directory.
+
+@item
+The data directory is @file{var} rather than @file{data}.
+
+@item
+@code{mysql_install_db} is installed in the @file{/usr/local/bin} directory
+rather than in @file{/usr/local/mysql/scripts}.
+
+@item
+The header file and library directories are @file{include/mysql} and
+@file{lib/mysql} rather than @file{include} and @file{lib}.
+@end itemize
+
+You can create your own binary installation from a compiled source
+distribution, by executing the script @file{scripts/make_binary_distribution}.
+
+@node Installing binary, Installing source, Installation layouts, Installing
+@section Installing a MySQL binary distribution
+
+@menu
+* Linux-RPM:: Linux RPM files
+* Building clients:: Building client programs
+* Binary install system issues:: System-specific issues
+@end menu
+
+You need the following tools to install a @strong{MySQL} binary distribution:
+
+@itemize @bullet
+@item
+GNU @code{gunzip} to uncompress the distribution.
+
+@item
+A reasonable @code{tar} to unpack the distribution. GNU @code{tar} is
+known to work.
+@end itemize
+
+@cindex RPM
+@cindex RedHat Package Manager
+An alternative installation method under Linux is to use RPM (RedHat Package
+Manager) distributions. @xref{Linux-RPM}.
+
+@c texi2html fails to split chapters if I use strong for all of this.
+If you run into problems, @strong{PLEASE ALWAYS USE} @code{mysqlbug} when
+posting questions to @email{mysql@@lists.mysql.com}. Even if the problem
+isn't a bug, @code{mysqlbug} gathers system information that will help others
+solve your problem. By not using @code{mysqlbug}, you lessen the likelihood
+of getting a solution to your problem! You will find @code{mysqlbug} in the
+@file{bin} directory after you unpack the distribution. @xref{Bug reports}.
+
+The basic commands you must execute to install and use a @strong{MySQL}
+binary distribution are:
+
+@example
+shell> gunzip < mysql-VERSION-OS.tar.gz | tar xvf -
+shell> ln -s mysql-VERSION-OS mysql
+shell> cd mysql
+shell> scripts/mysql_install_db
+shell> bin/safe_mysqld &
+@end example
+
+You can add new users using the @code{bin/mysql_setpermission} script if
+you install the @code{DBI} and @code{Msql-Mysql-modules} Perl modules.
+
+Here follows a more detailed description:
+
+To install a binary distribution, follow the steps below, then proceed
+to @ref{Post-installation}, for post-installation setup and testing:
+
+@enumerate
+@item
+Pick the directory under which you want to unpack the distribution, and move
+into it. In the example below, we unpack the distribution under
+@file{/usr/local} and create a directory @file{/usr/local/mysql} into which
+@strong{MySQL} is installed. (The following instructions therefore assume
+you have permission to create files in @file{/usr/local}. If that directory
+is protected, you will need to perform the installation as @code{root}.)
+
+@item
+Obtain a distribution file from one of the sites listed in
+@ref{Getting MySQL, , Getting @strong{MySQL}}.
+
+@strong{MySQL} binary distributions are provided as compressed @code{tar}
+archives and have names like @file{mysql-VERSION-OS.tar.gz}, where
+@code{VERSION} is a number (e.g., @code{3.21.15}), and @code{OS} indicates
+the type of operating system for which the distribution is intended (e.g.,
+@code{pc-linux-gnu-i586}).
+
+@item
+Unpack the distribution and create the installation directory:
+
+@example
+shell> gunzip < mysql-VERSION-OS.tar.gz | tar xvf -
+shell> ln -s mysql-VERSION-OS mysql
+@end example
+
+The first command creates a directory named @file{mysql-VERSION-OS}. The
+second command makes a symbolic link to that directory. This lets you refer
+more easily to the installation directory as @file{/usr/local/mysql}.
+
+@item
+Change into the installation directory:
+
+@example
+shell> cd mysql
+@end example
+
+You will find several files and subdirectories in the @code{mysql} directory.
+The most important for installation purposes are the @file{bin} and
+@file{scripts} subdirectories.
+
+@table @file
+@item bin
+@tindex PATH environment variable
+@tindex Environment variable, PATH
+This directory contains client programs and the server
+You should add the full pathname of this directory to your
+@code{PATH} environment variable so that your shell finds the @strong{MySQL}
+programs properly. @xref{Environment variables}.
+
+@item scripts
+This directory contains the @code{mysql_install_db} script used to initialize
+the server access permissions.
+@end table
+
+@item
+If you would like to use @code{mysqlaccess} and have the @strong{MySQL}
+distribution in some nonstandard place, you must change the location where
+@code{mysqlaccess} expects to find the @code{mysql} client. Edit the
+@file{bin/mysqlaccess} script at approximately line 18. Search for a line
+that looks like this:
+
+@example
+$MYSQL = '/usr/local/bin/mysql'; # path to mysql executable
+@end example
+
+Change the path to reflect the location where @code{mysql} actually is
+stored on your system. If you do not do this, you will get a @code{broken
+pipe} error when you run @code{mysqlaccess}.
+
+@item
+Create the @strong{MySQL} grant tables (necessary only if you haven't
+installed @strong{MySQL} before):
+@example
+shell> scripts/mysql_install_db
+@end example
+
+Note that @strong{MySQL} versions older than 3.22.10 started the
+@strong{MySQL} server when you run @code{mysql_install_db}. This is no
+longer true!
+
+@item
+If you want to install support for the Perl @code{DBI}/@code{DBD} interface,
+see @ref{Perl support}.
+
+@item
+If you would like @strong{MySQL} to start automatically when you boot your
+machine, you can copy @code{support-files/mysql.server} to the location where
+your system has its startup files. More information can be found in the
+@code{support-files/mysql.server} script itself, and in @ref{Automatic
+start}.
+
+@end enumerate
+
+After everything has been unpacked and installed, you should initialize
+and test your distribution.
+
+You can start the @strong{MySQL} server with the following command:
+
+@example
+shell> bin/safe_mysqld &
+@end example
+
+@xref{Post-installation}.
+
+@cindex RPM
+@cindex RedHat Package Manager
+@c This node name is special
+@node Linux-RPM, Building clients, Installing binary, Installing binary
+@subsection Linux RPM notes
+
+The recommended way to install @strong{MySQL} on Linux is by using an RPM
+file. The @strong{MySQL} RPMs are currently being built on a RedHat 5.2
+system but should work on other versions of Linux that support @code{rpm} and
+use @code{glibc}.
+
+If you have problems with an RPM file, for example @code{Sorry, the host
+'xxxx' could not be looked up}, see @ref{Binary notes-Linux}.
+
+The RPM files you may want to use are:
+
+@itemize @bullet
+@item @code{MySQL-VERSION.i386.rpm}
+
+The @strong{MySQL} server. You will need this unless you only want to
+connect to another @strong{MySQL} server running on another machine.
+
+@item @code{MySQL-client-VERSION.i386.rpm}
+
+The standard @strong{MySQL} client programs. You probably always want to
+install this package.
+
+@item @code{MySQL-bench-VERSION.i386.rpm}
+
+Tests and benchmarks. Requires Perl and msql-mysql-modules RPMs.
+
+@item @code{MySQL-devel-VERSION.i386.rpm}
+
+Libraries and include files needed if you want to compile other
+@strong{MySQL} clients, such as the Perl modules.
+
+@item @code{MySQL-VERSION.src.rpm}
+
+This contains the source code for all of the above packages. It can also
+be used to try to build RPMs for other architectures (for example, Alpha
+or SPARC).
+@end itemize
+
+To see all files in an RPM package:
+@example
+shell> rpm -qpl MySQL-VERSION.i386.rpm
+@end example
+
+To perform a standard minimal installation, run this command:
+
+@example
+shell> rpm -i MySQL-VERSION.i386.rpm MySQL-client-VERSION.i386.rpm
+@end example
+
+To install just the client package:
+
+@example
+shell> rpm -i MySQL-client-VERSION.i386.rpm
+@end example
+
+The RPM places data in @file{/var/lib/mysql}. The RPM also creates the
+appropriate entries in @file{/etc/rc.d/} to start the server automatically
+at boot time. (This means that if you have performed a previous
+installation, you may want to make a copy of your previously-installed
+@strong{MySQL} startup file if you made any changes to it, so you don't lose
+your changes.)
+
+After installing the RPM file(s), the @file{mysqld} daemon should be running
+and you should now be able to start using @strong{MySQL}.
+@xref{Post-installation}.
+
+If something goes wrong, can find more information in the binary
+installation chapter. @xref{Installing binary}.
+
+
+@cindex Client programs, building
+@cindex Linking
+@node Building clients, Binary install system issues, Linux-RPM, Installing binary
+@subsection Building client programs
+
+If you compile @strong{MySQL} clients that you've written yourself or that
+you obtain from a third party, they must be linked using the
+@code{-lmysqlclient} option on the link command. You may also need to
+specify a @code{-L} option to tell the linker where to find the library. For
+example, if the library is installed in @file{/usr/local/mysql/lib}, use
+@code{-L/usr/local/mysql/lib -lmysqlclient} on the link command.
+
+For clients that use @strong{MySQL} header files, you may need to specify a
+@code{-I} option when you compile them (for example,
+@code{-I/usr/local/mysql/include}), so the compiler can find the header
+files.
+
+@node Binary install system issues, , Building clients, Installing binary
+@subsection System-specific issues
+
+@menu
+* Binary notes-Linux:: Linux notes
+* Binary notes-HP-UX:: HP-UX notes
+@end menu
+
+The following sections indicate some of the issues that have been observed
+on particular systems when installing @strong{MySQL} from a binary
+distribution.
+
+@node Binary notes-Linux, Binary notes-HP-UX, Binary install system issues, Binary install system issues
+@subsubsection Linux notes
+
+@strong{MySQL} needs at least Linux 2.0.
+
+The binary release is linked with @code{-static}, which means you not
+normally need not worry about which version of the system libraries you
+have. You need not install LinuxThreads, either. A program linked with
+@code{-static} is slightly bigger than a dynamically-linked program but
+also slightly faster (3-5%). One problem however is that you can't use
+user definable functions (UDFs) with a statically-linked program. If
+you are going to write or use UDF functions (this is something only for
+C or C++ programmers) you must compile @strong{MySQL} yourself, using
+dynamic linking.
+
+If you are using a @code{libc}-based system (instead of a @code{glibc2}
+system), you will probably get some problems with hostname resolving and
+getpwnam() with the binary release. (This is because @code{glibc}
+unfortunately depends on some external libraries to resolve hostnames
+and getwpent() , even when compiled with @code{-static}). In this case
+you probably get the following error message when you run
+@code{mysql_install_db}:
+
+@example
+Sorry, the host 'xxxx' could not be looked up
+@end example
+
+or the following error when you try to run mysqld with the @code{--user}
+option:
+
+@example
+getpwnam: No such file or directory
+@end example
+
+You can solve this problem one of the following ways:
+
+@itemize @bullet
+@item
+Get a @strong{MySQL} source distribution (an RPM or the @code{tar}
+distribution) and install this instead.
+@item
+Execute @code{mysql_install_db --force}; This will not execute the
+@code{resolveip} test in @code{mysql_install_db}. The downside is that
+you can't use host names in the grant tables; you must use IP numbers
+instead (except for @code{localhost}). If you are using an old @strong{MySQL}
+release that doesn't support @code{--force} you have to remove the
+@code{resolveip} test in @code{mysql_install} with an editor.
+@item
+Start mysqld with @code{su} instead of using @code{--user}.
+@end itemize
+
+The Linux-Intel binary and RPM releases of @strong{MySQL} are configured
+for the highest possible speed. We are always trying to use the fastest
+stable compiler available.
+
+@strong{MySQL} Perl support requires Perl 5.004_03 or newer.
+
+@node Binary notes-HP-UX, , Binary notes-Linux, Binary install system issues
+@subsubsection HP-UX notes
+
+Some of the binary distributions of @strong{MySQL} for HP-UX is
+distributed as an HP depot file and as a tar file. To use the depot
+file you must be running at least HP-UX 10.x to have access to HP's
+software depot tools.
+
+The HP version of @strong{MySQL} was compiled on an HP 9000/8xx server
+under HP-UX 10.20, and uses MIT-pthreads. It is known to work
+well under this configuration.
+@strong{MySQL} 3.22.26 and newer can also be built with HP's native
+thread package.
+
+Other configurations that may work:
+
+@itemize @bullet
+@item
+HP 9000/7xx running HP-UX 10.20+
+@item
+HP 9000/8xx running HP-UX 10.30
+@end itemize
+
+The following configurations almost definitely won't work:
+
+@itemize @bullet
+@item
+HP 9000/7xx or 8xx running HP-UX 10.x where x < 2
+@item
+HP 9000/7xx or 8xx running HP-UX 9.x
+@end itemize
+
+To install the distribution, use one of the commands below, where
+@code{/path/to/depot} is the full pathname of the depot file:
+
+@itemize @bullet
+@item
+To install everything, including the server, client and development tools:
+
+@example
+shell> /usr/sbin/swinstall -s /path/to/depot mysql.full
+@end example
+
+@item
+To install only the server:
+
+@example
+shell> /usr/sbin/swinstall -s /path/to/depot mysql.server
+@end example
+
+@item
+To install only the client package:
+
+@example
+shell> /usr/sbin/swinstall -s /path/to/depot mysql.client
+@end example
+
+@item
+To install only the development tools:
+
+@example
+shell> /usr/sbin/swinstall -s /path/to/depot mysql.developer
+@end example
+@end itemize
+
+The depot places binaries and libraries in @file{/opt/mysql} and data in
+@file{/var/opt/mysql}. The depot also creates the appropriate entries in
+@file{/sbin/init.d} and @file{/sbin/rc2.d} to start the server automatically
+at boot time. Obviously, this entails being @code{root} to install.
+
+To install the HP-UX tar distribution, you must have a copy of GNU @code{tar}.
+
+@node Installing source, Compilation problems, Installing binary, Installing
+@section Installing a MySQL source distribution
+
+You need the following tools to build and install @strong{MySQL} from source:
+
+@itemize @bullet
+@item
+GNU @code{gunzip} to uncompress the distribution.
+
+@item
+A reasonable @code{tar} to unpack the distribution. GNU @code{tar} is
+known to work.
+
+@item
+A working ANSI C++ compiler. @code{gcc} >= 2.8.1, @code{egcs} >=
+1.0.2, SGI C++ and SunPro C++ are some of the compilers that are known to
+work. @code{libg++} is not needed when using @code{gcc}. @code{gcc}
+2.7.x has a bug that makes it impossible to compile some perfectly legal
+C++ files, such as @file{sql/sql_base.cc}. If you only have @code{gcc} 2.7.x,
+you must upgrade your @code{gcc} to be able to compile @strong{MySQL}.
+
+@item
+A good @code{make} program. GNU @code{make} is always recommended and is
+sometimes required. If you have problems, we recommend trying GNU
+@code{make} 3.75 or newer.
+@end itemize
+
+@c texi2html fails to split chapters if I use strong for all of this.
+If you run into problems, @strong{PLEASE ALWAYS USE @code{mysqlbug}} when
+posting questions to @email{mysql@@lists.mysql.com}. Even if the problem
+isn't a bug, @code{mysqlbug} gathers system information that will help others
+solve your problem. By not using @code{mysqlbug}, you lessen the likelihood
+of getting a solution to your problem! You will find @code{mysqlbug} in the
+@file{scripts} directory after you unpack the distribution. @xref{Bug
+reports}.
+
+@menu
+* Quick install:: Quick installation overview
+* Applying patches:: Applying patches
+* configure options:: Typical @code{configure} options
+@end menu
+
+@node Quick install, Applying patches, Installing source, Installing source
+@subsection Quick installation overview
+
+The basic commands you must execute to install a @strong{MySQL} source
+distribution are (from an unpacked @code{tar} file):
+
+@example
+shell> configure
+shell> make
+shell> make install
+shell> scripts/mysql_install_db
+shell> /usr/local/mysql/bin/safe_mysqld &
+@end example
+
+If you start from a source RPM, then do the following.
+
+@example
+shell> rpm --rebuild MySQL-VERSION.src.rpm
+@end example
+
+This will make a binary RPM that you can install.
+
+You can add new users using the @code{bin/mysql_setpermission} script if
+you install the @code{DBI} and @code{Msql-Mysql-modules} Perl modules.
+
+Here follows a more detailed description:
+
+To install a source distribution, follow the steps below, then proceed
+to @ref{Post-installation}, for post-installation initialization and testing.
+
+@enumerate
+@item
+Pick the directory under which you want to unpack the distribution, and move
+into it.
+
+@item
+Obtain a distribution file from one of the sites listed in
+@ref{Getting MySQL, , Getting @strong{MySQL}}.
+
+@strong{MySQL} source distributions are provided as compressed @code{tar}
+archives and have names like @file{mysql-VERSION.tar.gz}, where
+@code{VERSION} is a number like @value{mysql_version}.
+
+@item
+Unpack the distribution into the current directory:
+@example
+shell> gunzip < mysql-VERSION.tar.gz | tar xvf -
+@end example
+This command creates a directory named @file{mysql-VERSION}.
+
+@item
+Change into the top-level directory of the unpacked distribution:
+@example
+shell> cd mysql-VERSION
+@end example
+
+@item
+Configure the release and compile everything:
+@example
+shell> ./configure --prefix=/usr/local/mysql
+shell> make
+@end example
+When you run @code{configure}, you might want to specify some options.
+Run @code{./configure --help} for a list of options.
+@ref{configure options, , @code{configure} options}, discusses some of the
+more useful options.
+
+If @code{configure} fails, and you are going to send mail to
+@email{mysql@@lists.mysql.com} to ask for assistance, please include any
+lines from @file{config.log} that you think can help solve the problem. Also
+include the last couple of lines of output from @code{configure} if
+@code{configure} aborts. Post the bug report using the @code{mysqlbug}
+script. @xref{Bug reports}.
+
+If the compile fails, see @ref{Compilation problems}, for help with
+a number of common problems.
+
+@item
+Install everything:
+@example
+shell> make install
+@end example
+You might need to run this command as @code{root}.
+
+@item
+Create the @strong{MySQL} grant tables (necessary only if you haven't
+installed @strong{MySQL} before):
+@example
+shell> scripts/mysql_install_db
+@end example
+
+Note that @strong{MySQL} versions older than 3.22.10 started the
+@strong{MySQL} server when you run @code{mysql_install_db}. This is no
+longer true!
+
+@item
+If you want to install support for the Perl @code{DBI}/@code{DBD} interface,
+see @ref{Perl support}.
+
+@item
+If you would like @strong{MySQL} to start automatically when you boot your
+machine, you can copy @code{support-files/mysql.server} to the location where
+your system has its startup files. More information can be found in the
+@code{support-files/mysql.server} script itself, and in @ref{Automatic
+start}.
+@end enumerate
+
+After everything has been installed, you should initialize and test your
+distribution.
+
+You can start the @strong{MySQL} server with the following command,
+where @code{BINDIR} is the directory in which @code{safe_mysqld} is
+installed (@file{/usr/local/bin} by default):
+
+@example
+shell> BINDIR/safe_mysqld &
+@end example
+
+If that command fails immediately with @code{mysqld daemon ended} then you can
+find some information in the file
+@file{mysql-data-directory/'hostname'.err}. The likely reason is that
+you already have another @code{mysqld} server running. @xref{Multiple
+servers}.
+
+@xref{Post-installation}.
+
+@node Applying patches, configure options, Quick install, Installing source
+@subsection Applying patches
+
+Sometimes patches appear on the mailing list or are placed in the
+@uref{http://www.mysql.com/Downloads/Patches,patches area} of the
+@strong{MySQL} Web site.
+
+To apply a patch from the mailing list, save the message in which the patch
+appears in a file, change into the top-level directory of your @strong{MySQL}
+source tree and run these commands:
+
+@example
+shell> patch -p1 < patch-file-name
+shell> rm config.cache
+shell> make clean
+@end example
+
+Patches from the FTP site are distributed as plain text files or as files
+compressed with @code{gzip}. Apply a plain patch as shown above for
+mailing list patches. To apply a compressed patch, change into the
+top-level directory of your @strong{MySQL} source tree and run these
+commands:
+
+@example
+shell> gunzip < patch-file-name.gz | patch -p1
+shell> rm config.cache
+shell> make clean
+@end example
+
+After applying a patch, follow the instructions for a normal source install,
+beginning with the @code{./configure} step. After running the @code{make
+install} step, restart your @strong{MySQL} server.
+
+You may need to bring down any currently running server before you run
+@code{make install}. (Use @code{mysqladmin shutdown} to do this.) Some
+systems do not allow you to install a new version of a program if it replaces
+the version that is currently executing.
+
+@node configure options, , Applying patches, Installing source
+@subsection Typical @code{configure} options
+
+The @code{configure} script gives you a great deal of control over how
+you configure your @strong{MySQL} distribution. Typically you do this
+using options on the @code{configure} command line. You can also affect
+@code{configure} using certain environment variables. @xref{Environment
+variables}. For a list of options supported by @code{configure}, run
+this command:
+
+@example
+shell> ./configure --help
+@end example
+
+Some of the more commonly-used @code{configure} options are described below:
+
+@itemize @bullet
+@item
+To compile just the @strong{MySQL} client libraries and client programs and
+not the server, use the @code{--without-server} option:
+
+@example
+shell> ./configure --without-server
+@end example
+
+If you don't have a C++ compiler, @code{mysql} will not compile (it is the
+one client program that requires C++). In this case,
+you can remove the code in @code{configure} that tests for the C++ compiler
+and then run @code{./configure} with the @code{--without-server} option. The
+compile step will still try to build @code{mysql}, but you can ignore any
+warnings about @file{mysql.cc}. (If @code{make} stops, try @code{make -k}
+to tell it to continue with the rest of the build even if errors occur.)
+
+@item
+If you don't want your log files and database directories located under
+@file{/usr/local/var}, use a @code{configure} command something like one
+of these:
+@example
+shell> ./configure --prefix=/usr/local/mysql
+shell> ./configure --prefix=/usr/local \
+ --localstatedir=/usr/local/mysql/data
+@end example
+The first command changes the installation prefix so that everything is
+installed under @file{/usr/local/mysql} rather than the default of
+@file{/usr/local}. The second command preserves the default installation
+prefix, but overrides the default location for database directories
+(normally @file{/usr/local/var}) and changes it to
+@code{/usr/local/mysql/data}.
+
+@item
+If you are using Unix and you want the @strong{MySQL} socket located somewhere
+other than the default location (normally in the directory @file{/tmp} or
+@file{/var/run}, use a @code{configure} command like this:
+@example
+shell> ./configure --with-unix-socket-path=/usr/local/mysql/tmp/mysql.sock
+@end example
+Note that the given file must be an absolute pathname!
+
+@item
+If you want to compile statically-linked programs (e.g., to make a binary
+distribution, to get more speed or to work around problems with some RedHat
+distributions), run @code{configure} like this:
+
+@example
+shell> ./configure --with-client-ldflags=-all-static \
+ --with-mysqld-ldflags=-all-static
+@end example
+
+@item
+If you are using @code{gcc} and don't have @code{libg++} or @code{libstdc++}
+installed, you can tell @code{configure} to use @code{gcc} as your C++
+compiler:
+
+@tindex CC environment variable
+@tindex Environment variable, CC
+@tindex CXX environment variable
+@tindex Environment variable, CXX
+@example
+shell> CC=gcc CXX=gcc ./configure
+@end example
+
+When you use @code{gcc} as your C++ compiler, it will not attempt to link in
+@code{libg++} or @code{libstdc++}.
+
+If the build fails and produces errors about your compiler or linker not
+being able to create the shared library @file{libmysqlclient.so.#} (@samp{#}
+is a version number), you can work around this problem by giving the
+@code{--disable-shared} option to @code{configure}. In this case,
+@code{configure} will not build a shared @code{libmysqlclient.so.#} library.
+
+@item
+You can configure @strong{MySQL} not to use @code{DEFAULT} column values for
+non-@code{NULL} columns (i.e., columns that are not allowed to be
+@code{NULL}). This causes @code{INSERT} statements to generate an error
+unless you explicitly specify values for all columns that require a
+non-@code{NULL} value. To suppress use of default values, run
+@code{configure} like this:
+
+@tindex CXXFLAGS environment variable
+@tindex Environment variable, CXXFLAGS
+@example
+shell> CXXFLAGS=-DDONT_USE_DEFAULT_FIELDS ./configure
+@end example
+
+@item
+By default, @strong{MySQL} uses the ISO-8859-1 (Latin1) character set. To
+change the default set, use the @code{--with-charset} option:
+@example
+shell> ./configure --with-charset=CHARSET
+@end example
+@code{CHARSET} may be one of @code{big5}, @code{cp1251}, @code{cp1257},
+@code{czech}, @code{danish},@code{dec8}, @code{dos}, @code{euc_kr},
+@code{gb2312}, @code{gbk}, @code{german1}, @code{hebrew}, @code{hp8},
+@code{hungarian}, @code{koi8_ru}, @code{koi8_ukr}, @code{latin1}, @code{latin2},
+@code{sjis}, @code{swe7}, @code{tis620}, @code{ujis}, @code{usa7},
+@code{win1251} or @code{win1251ukr}.
+@xref{Character sets}.
+
+If you want to convert characters between the server and the client,
+you should take a look at the @code{SET OPTION CHARACTER SET} command.
+@xref{SET OPTION, , @code{SET OPTION}}.
+
+@cindex @code{myisamchk}
+@strong{Warning:} If you change character sets after having created any
+tables, you will have to run @code{myisamchk -r -q} on every table. Your
+indexes may be sorted incorrectly otherwise. (This can happen if you
+install @strong{MySQL}, create some tables, then reconfigure
+@strong{MySQL} to use a different character set and reinstall it.)
+
+@item
+To configure
+@strong{MySQL} with debugging code, use the @code{--with-debug} option:
+@example
+shell> ./configure --with-debug
+@end example
+This causes a safe memory allocator to be included that can find some errors
+and that provides output about what is happening.
+@xref{Debugging server}.
+
+@item
+If your client programs are using threads, you need to compile the
+@strong{MySQL} client library to be thread safe with
+@code{--with-thread-safe-client}; this forces the library to use thread
+safe functions calls for some functions that are not thread safe by
+default. You pay a very small performance penalty by doing this, but
+generally it's quite safe to use this option.
+
+@item
+Options that pertain to particular systems can be found in the
+system-specific sections later in this chapter.
+@xref{Source install system issues}.
+@end itemize
+
+@node Compilation problems, MIT-pthreads, Installing source, Installing
+@section Problems compiling?
+
+All @strong{MySQL} programs compile cleanly for us with no warnings on
+Solaris using @code{gcc}. On other systems, warnings may occur due to
+differences in system include files. See @ref{MIT-pthreads}, for warnings
+that may occur when using MIT-pthreads. For other problems, check the list
+below.
+
+The solution to many problems involves reconfiguring. If you do need to
+reconfigure, take note of the following:
+
+@cindex Running @code{configure} after prior invocation
+@cindex @code{configure}, running after prior invocation
+@itemize @bullet
+@item
+If @code{configure} is run after it already has been run, it may use
+information that was gathered during its previous invocation. This
+information is stored in @file{config.cache}. When @code{configure} starts
+up, it looks for that file and reads its contents if it exists, on the
+assumption that the information is still correct. That assumption is invalid
+when you reconfigure.
+@item
+Each time you run @code{configure}, you must run @code{make} again
+to recompile. However, you may want to remove old object files from previous
+builds first, because they were compiled using different configuration options.
+@end itemize
+
+To prevent old configuration information or object files from being used,
+run these commands before rerunning @code{configure}:
+
+@example
+shell> rm config.cache
+shell> make clean
+@end example
+
+Alternatively, you can run @code{make distclean}.
+
+The list below describes some of the problems compiling @strong{MySQL}
+that have been found to occur most often:
+
+@itemize @bullet
+@item
+@cindex @code{cc1plus} problems
+@cindex @code{fatal signal 11}
+@cindex @code{sql_yacc.cc} problems
+@cindex Internal compiler errors
+@cindex Virtual memory problems while compiling
+If you get errors when compiling @file{sql_yacc.cc} such as the ones shown
+below, you have probably run out of memory or swap space:
+
+@example
+Internal compiler error: program cc1plus got fatal signal 11
+ or
+Out of virtual memory
+ or
+Virtual memory exhausted
+@end example
+
+The problem is that @code{gcc} requires huge amounts of memory to compile
+@file{sql_yacc.cc} with inline functions. Try running @code{configure} with
+the @code{--with-low-memory} option:
+
+@example
+shell> ./configure --with-low-memory
+@end example
+
+This option causes @code{-fno-inline} to be added to the compile line if you
+are using @code{gcc} and @code{-O0} if you are using something else. You
+should try the @code{--with-low-memory} option even if you have so much
+memory and swap space that you think you can't possibly have run out. This
+problem has been observed to occur even on systems with generous hardware
+configurations, and the @code{--with-low-memory} option usually fixes it.
+
+@item
+By default, @code{configure} picks @code{c++} as the compiler name and
+GNU @code{c++} links with @code{-lg++}. If you are using @code{gcc},
+that behavior can cause problems during configuration such as this:
+
+@cindex C++ compiler cannot create executables
+@example
+configure: error: installation or configuration problem:
+C++ compiler cannot create executables.
+@end example
+
+@tindex CXX environment variable
+@tindex Environment variable, CXX
+You might also observe problems during compilation related to
+@code{g++}, @code{libg++} or @code{libstdc++}.
+
+One cause of these problems is that you may not have @code{g++}, or you may
+have @code{g++} but not @code{libg++} or @code{libstdc++}. Take a look at
+the @file{config.log} file. It should contain the exact reason why your c++
+compiler didn't work! To work around these problems, you can use @code{gcc}
+as your C++ compiler. Try setting the environment variable @code{CXX} to
+@code{"gcc -O3"}. For example:
+
+@tindex CXX environment variable
+@tindex Environment variables, CXX
+@example
+shell> CXX="gcc -O3" ./configure
+@end example
+
+This works because @code{gcc} compiles C++ sources as well as @code{g++}
+does, but does not link in @code{libg++} or @code{libstdc++} by default.
+
+Another way to fix these problems, of course, is to install @code{g++},
+@code{libg++} and @code{libstdc++}.
+
+@item
+If your compile fails with errors such as any of the following,
+you must upgrade your version of @code{make} to GNU @code{make}:
+
+@example
+making all in mit-pthreads
+make: Fatal error in reader: Makefile, line 18:
+Badly formed macro assignment
+ or
+make: file `Makefile' line 18: Must be a separator (:
+ or
+pthread.h: No such file or directory
+@end example
+
+@cindex Solaris troubleshooting
+@cindex FreeBSD troubleshooting
+@cindex Troubleshooting, Solaris
+@cindex Troubleshooting, FreeBSD
+Solaris and FreeBSD are known to have troublesome @code{make} programs.
+
+GNU @code{make} version 3.75 is known to work.
+
+@tindex CC environment variable
+@tindex Environment variable, CC
+@tindex CXX environment variable
+@tindex Environment variable, CXX
+@tindex CFLAGS environment variable
+@tindex Environment variable, CFLAGS
+@tindex CXXFLAGS environment variable
+@tindex Environment variable, CXXFLAGS
+@item
+If you want to define flags to be used by your C or C++ compilers, do so by
+adding the flags to the @code{CFLAGS} and @code{CXXFLAGS} environment
+variables. You can also specify the compiler names this way using @code{CC}
+and @code{CXX}. For example:
+
+@example
+shell> CC=gcc
+shell> CFLAGS=-O6
+shell> CXX=gcc
+shell> CXXFLAGS=-O6
+shell> export CC CFLAGS CXX CXXFLAGS
+@end example
+
+See @ref{MySQL binaries}, for a list of flag definitions that have been found
+to be useful on various systems.
+
+@item
+If you get an error message like this,
+you need to upgrade your @code{gcc} compiler:
+
+@example
+client/libmysql.c:273: parse error before `__attribute__'
+@end example
+
+@code{gcc} 2.8.1 is known to work, but we recommend using @code{gcc} 2.95.2 or
+@code{egcs} 1.0.3a instead.
+
+@item
+If you get errors such as those shown below when compiling @code{mysqld},
+@code{configure} didn't correctly detect the type of the last argument to
+@code{accept()}, @code{getsockname()} or @code{getpeername()}:
+
+@example
+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);
+@end example
+
+To fix this, edit the @file{config.h} file (which is generated by
+@code{configure}). Look for these lines:
+
+@example
+/* Define as the base type of the last arg to accept */
+#define SOCKET_SIZE_TYPE XXX
+@end example
+
+Change @code{XXX} to @code{size_t} or @code{int}, depending on your
+operating system. (Note that you will have to do this each time you run
+@code{configure}, because @code{configure} regenerates @file{config.h}.)
+
+@item
+The @file{sql_yacc.cc} file is generated from @file{sql_yacc.yy}. Normally
+the build process doesn't need to create @file{sql_yacc.cc}, because
+@strong{MySQL} comes with an already-generated copy. However, if you do need
+to recreate it, you might encounter this error:
+
+@example
+"sql_yacc.yy", line xxx fatal: default action causes potential...
+@end example
+
+This is a sign that your version of @code{yacc} is deficient.
+You probably need to install @code{bison} (the GNU version of @code{yacc})
+and use that instead.
+
+@item
+If you need to debug @code{mysqld} or a @strong{MySQL} client, run
+@code{configure} with the @code{--with-debug} option, then recompile and
+link your clients with the new client library.
+@xref{Debugging client}.
+@end itemize
+
+@node MIT-pthreads, Perl support, Compilation problems, Installing
+@section MIT-pthreads notes
+
+This section describes some of the issues involved in using MIT-pthreads.
+
+Note that on Linux you should NOT use MIT-pthreads but install LinuxThreads!
+@xref{Linux}.
+
+If your system does not provide native thread support, you will need to
+build @strong{MySQL} using the MIT-pthreads package. This includes
+most FreeBSD systems, SunOS 4.x, Solaris 2.4 and earlier, and some others.
+@xref{Which OS}.
+
+@itemize @bullet
+@item
+On most systems, you can force MIT-pthreads to be used by running
+@code{configure} with the @code{--with-mit-threads} option:
+
+@example
+shell> ./configure --with-mit-threads
+@end example
+
+Building in a non-source directory is not supported when using
+MIT-pthreads, because we want to minimize our changes to this code.
+
+@item
+MIT-pthreads doesn't support the @code{AF_UNIX} protocol used to implement
+Unix sockets. This means that if you compile using MIT-pthreads, all
+connections must be made using TCP/IP (which is a little slower). If you
+find after building @strong{MySQL} that you cannot connect to the local
+server, it may be that your client is attempting to connect to
+@code{localhost} using a Unix socket as the default. Try making a TCP/IP
+connection with @code{mysql} by using a host option (@code{-h} or
+@code{--host}) to specify the local host name explicitly.
+
+@item
+The checks that determine whether or not to use MIT-pthreads occur only
+during the part of the configuration process that deals with the server
+code. If you have configured the distribution using @code{--without-server}
+to build only the client code, clients will not know whether or not
+MIT-pthreads is being used and will use Unix socket connections by default.
+Because Unix sockets do not work under MIT-pthreads, this means you will need
+to use @code{-h} or @code{--host} when you run client programs.
+
+@item
+When @strong{MySQL} is compiled using MIT-pthreads, system locking is
+disabled by default for performance reasons. You can tell the server to use
+system locking with the @code{--use-locking} option.
+
+@item
+Sometimes the pthread @code{bind()} command fails to bind to a socket without
+any error message (at least on Solaris). The result is that all connections
+to the server fail. For example:
+
+@example
+shell> mysqladmin version
+mysqladmin: connect to server at '' failed;
+error: 'Can't connect to mysql server on localhost (146)'
+@end example
+
+The solution to this is to kill the @code{mysqld} server and restart it.
+This has only happened to us when we have forced the server down and done
+a restart immediately.
+
+@item
+With MIT-pthreads, the @code{sleep()} system call isn't interruptible with
+@code{SIGINT} (break). This is only noticeable when you run @code{mysqladmin
+--sleep}. You must wait for the @code{sleep()} call to terminate before the
+interrupt is served and the process stops.
+
+@item
+When linking you may receive warning messages like these (at least on
+Solaris); they can be ignored:
+
+@example
+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
+@end example
+
+@item
+Some other warnings also can be ignored:
+
+@example
+implicit declaration of function `int strtoll(...)'
+implicit declaration of function `int strtoul(...)'
+@end example
+
+@item
+We haven't gotten @code{readline} to work with MIT-pthreads. (This isn't
+needed, but may be interesting for someone.)
+@end itemize
+
+@node Perl support, Source install system issues, MIT-pthreads, Installing
+@section Perl installation comments
+
+@menu
+* Perl installation:: Installing Perl on Unix
+* ActiveState Perl:: Installing ActiveState Perl on Win32
+* Win32 Perl:: Installing the @strong{MySQL} Perl distribution on Win32
+* Perl support problems:: Problems using the Perl @code{DBI}/@code{DBD} interface
+@end menu
+
+@node Perl installation, ActiveState Perl, Perl support, Perl support
+@subsection Installing Perl on Unix
+
+Perl support for @strong{MySQL} is provided by means of the
+@code{DBI}/@code{DBD} client interface. @xref{Perl}. The Perl
+@code{DBD}/@code{DBI} client code requires Perl 5.004 or later. The
+interface @emph{will not work} if you have an older version of Perl.
+
+@strong{MySQL} Perl support also requires that you've installed
+@strong{MySQL} client programming support. If you installed @strong{MySQL}
+from RPM files, client programs are in the client RPM, but client programming
+support is in the developer RPM. Make sure you've installed the latter RPM.
+
+As of release 3.22.8, Perl support is distributed separately from the main
+@strong{MySQL} distribution. If you want to install Perl support, the files
+you will need can be obtained from @uref{http://www.mysql.com/Downloads/Contrib/}.
+
+The Perl distributions are provided as compressed @code{tar} archives and
+have names like @file{MODULE-VERSION.tar.gz}, where @code{MODULE} is the
+module name and @code{VERSION} is the version number. You should get the
+@code{Data-Dumper}, @code{DBI}, and @code{Msql-Mysql-modules} distributions
+and install them in that order. The installation procedure is shown below.
+The example shown is for the @code{Data-Dumper} module, but the procedure is
+the same for all three distributions.
+
+@enumerate
+@item
+Unpack the distribution into the current directory:
+@example
+shell> gunzip < Data-Dumper-VERSION.tar.gz | tar xvf -
+@end example
+This command creates a directory named @file{Data-Dumper-VERSION}.
+
+@item
+Change into the top-level directory of the unpacked distribution:
+@example
+shell> cd Data-Dumper-VERSION
+@end example
+
+@item
+Build the distribution and compile everything:
+@example
+shell> perl Makefile.PL
+shell> make
+shell> make test
+shell> make install
+@end example
+@end enumerate
+
+The @code{make test} command is important, because it verifies that the
+module is working. Note that when you run that command during the
+@code{Msql-Mysql-modules} installation to exercise the interface code, the
+@strong{MySQL} server must be running or the test will fail.
+
+It is a good idea to rebuild and reinstall the @code{Msql-Mysql-modules}
+distribution whenever you install a new release of @strong{MySQL},
+particularly if you notice symptoms such as all your @code{DBI} scripts
+dumping core after you upgrade @strong{MySQL}.
+
+If you don't have the right to install Perl modules in the system directory
+or if you to install local Perl modules, the following reference may help
+you:
+
+@example
+@uref{http://www.iserver.com/support/contrib/perl5/modules.html}
+@end example
+
+Look under the heading
+@code{Installing New Modules that Require Locally Installed Modules}.
+
+@node ActiveState Perl, Win32 Perl, Perl installation, Perl support
+@subsection Installing ActiveState Perl on Win32
+
+To install the @strong{MySQL} @code{DBD} module with ActiveState Perl on
+Win32, you should do the following:
+
+@itemize @bullet
+@item Open a DOS shell.
+@item If required, set the HTTP_proxy variable. For example, you might try:
+@code{set HTTP_proxy=my.proxy.com:3128}
+@item Start the PPM program: @code{C:\perl\bin\ppm.pl}
+@item If you have not already done so, install @code{DBI}: @code{install DBI}
+@item If this succeeds, install @code{ftp://ftp.de.uu.net/pub/CPAN/authors/id/JWIED/DBD-mysql-1.2212.x86.ppd}
+@end itemize
+
+The above should work at least with ActiveState Perl 5.6.
+
+If you can't get the above to work, you should instead install the
+@strong{MyODBC} driver and connect to @strong{MySQL} server through
+ODBC.
+
+@example
+use DBI;
+$dbh= DBI->connect("DBI:ODBC:$dsn","$user","$password") ||
+ die "Got error $DBI::errstr when connecting to $dsn\n";
+@end example
+
+@node Win32 Perl, Perl support problems, ActiveState Perl, Perl support
+@subsection Installing the MySQL Perl distribution on Win32
+
+The @strong{MySQL} Perl distribution contains @code{DBI},
+@code{DBD:MySQL} and @code{DBD:ODBC}.
+
+@itemize @bullet
+@item Get the Perl distribution for Win32 from
+@uref{http://www.mysql.com/download.html}.
+@item Unzip the distribution in @code{C:} so that you get a @file{C:\PERL} directory.
+@item Add the directory @file{C:\PERL\BIN} to your path.
+@item Add the directory @file{C:\PERL\BIN\MSWin32-x86-thread} or
+@file{C:\PERL\BIN\MSWin32-x86} to your path.
+@item Test that @code{perl} works by executing @code{perl -v} in a DOS shell.
+@end itemize
+
+@node Perl support problems, , Win32 Perl, Perl support
+@subsection Problems using the Perl @code{DBI}/@code{DBD} interface
+
+If Perl reports that it can't find the @code{../mysql/mysql.so} module,
+then the problem is probably that Perl can't locate the shared library
+@file{libmysqlclient.so}.
+
+You can fix this by any of the following methods:
+
+@itemize @bullet
+@item
+Compile the @code{Msql-Mysql-modules} distribution with @code{perl
+Makefile.PL -static -config} rather than @code{perl Makefile.PL}
+
+@item
+Copy @code{libmysqlclient.so} to the directory where your other shared
+libraries are located (probably @file{/usr/lib} or @file{/lib}).
+
+@item
+On @code{Linux} you can add the pathname of the directory where
+@code{libmysqlclient.so} is located to the @file{/etc/ld.so.conf} file.
+
+@item
+@tindex LD_RUN_PATH environment variable
+@tindex Environment variable, LD_RUN_PATH
+Add the pathname of the directory where @code{libmysqlclient.so} is located
+to the @code{LD_RUN_PATH} environment variable.
+@end itemize
+
+If you get the following errors from @code{DBD-mysql},
+you are probably using @code{gcc} (or using an old binary compiled with
+@code{gcc}):
+
+@example
+/usr/bin/perl: can't resolve symbol '__moddi3'
+/usr/bin/perl: can't resolve symbol '__divdi3'
+@end example
+
+Add @code{-L/usr/lib/gcc-lib/... -lgcc} to the link command when the
+@file{mysql.so} library gets built (check the output from @code{make} for
+@file{mysql.so} when you compile the Perl client). The @code{-L} option
+should specify the pathname of the directory where @file{libgcc.a} is located
+on your system.
+
+Another cause of this problem may be that Perl and @strong{MySQL} aren't both
+compiled with @code{gcc}. In this case, you can solve the mismatch by
+compiling both with @code{gcc}.
+
+If you want to use the Perl module on a system that doesn't support dynamic
+linking (like SCO) you can generate a static version of Perl that includes
+@code{DBI} and @code{DBD-mysql}. The way this works is that you generate a
+version of Perl with the @code{DBI} code linked in and install it on top of
+your current Perl. Then you use that to build a version of Perl that
+additionally has the @code{DBD} code linked in, and install that.
+
+On SCO, you must have the following environment variables set:
+
+@example
+shell> LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:/usr/progressive/lib
+or
+shell> LD_LIBRARY_PATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:/usr/progressive/lib:/usr/skunk/lib
+shell> LIBPATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:/usr/progressive/lib:/usr/skunk/lib
+shell> MANPATH=scohelp:/usr/man:/usr/local1/man:/usr/local/man:/usr/skunk/man:
+@end example
+
+First, create a Perl that includes a statically-linked @code{DBI} by running
+these commands in the directory where your @code{DBI} distribution is
+located:
+
+@example
+shell> perl Makefile.PL -static -config
+shell> make
+shell> make install
+shell> make perl
+@end example
+
+Then you must install the new Perl. The output of @code{make perl} will
+indicate the exact @code{make} command you will need to execute to perform
+the installation. On SCO, this is @code{make -f Makefile.aperl inst_perl
+MAP_TARGET=perl}.
+
+Next, use the just-created Perl to create another Perl that also includes a
+statically-linked @code{DBD::mysql} by running these commands in the
+directory where your @code{Msql-Mysql-modules} distribution is located:
+
+@example
+shell> perl Makefile.PL -static -config
+shell> make
+shell> make install
+shell> make perl
+@end example
+
+Finally, you should install this new Perl. Again, the output of @code{make
+perl} indicates the command to use.
+
+@node Source install system issues, Win32, Perl support, Installing
+@section System-specific issues
+
+The following sections indicate some of the issues that have been observed to
+occur on particular systems when installing @strong{MySQL} from a source
+distribution.
+
+@menu
+* Solaris:: Solaris notes
+* Solaris 2.7:: Solaris 2.7 / 2.8 notes
+* Solaris x86:: Solaris x86 notes
+* SunOS:: SunOS 4 notes
+* Linux:: Linux notes (all Linux versions)
+* Alpha-DEC-Unix:: Alpha-DEC-Unix notes
+* Alpha-DEC-OSF1:: Alpha-DEC-OSF1 notes
+* SGI-Irix:: SGI-Irix notes
+* FreeBSD:: FreeBSD notes
+* NetBSD:: NetBSD notes
+* OpenBSD:: OpenBSD 2.5 notes
+* BSDI:: BSD/OS notes
+* SCO:: SCO notes
+* SCO Unixware:: SCO Unixware 7.0 notes
+* IBM-AIX:: IBM-AIX notes
+* HP-UX 10.20:: HP-UX 10.20 notes
+* HP-UX 11.x:: HP-UX 11.x notes
+* MacOSX:: MacOSX notes
+@end menu
+
+@node Solaris, Solaris 2.7, Source install system issues, Source install system issues
+@subsection Solaris notes
+
+On Solaris, you may run into trouble even before you get the @strong{MySQL}
+distribution unpacked! Solaris @code{tar} can't handle long file names, so
+you may see an error like this when you unpack @strong{MySQL}:
+
+@example
+x mysql-3.22.12-beta/bench/Results/ATIS-mysql_odbc-NT_4.0-cmp-db2,informix,ms-sql,mysql,oracle,solid,sybase, 0 bytes, 0 tape blocks
+tar: directory checksum error
+@end example
+
+In this case, you must use GNU @code{tar} (@code{gtar}) to unpack the
+distribution. You can find a precompiled copy for Solaris at
+@uref{http://www.mysql.com/Downloads/}.
+
+Sun native threads work only on Solaris 2.5 and higher. For 2.4 and
+earlier versions, @strong{MySQL} will automatically use
+MIT-pthreads. @xref{MIT-pthreads}.
+
+If you get the following error from configure:
+
+@example
+checking for restartable system calls... configure: error can not run test
+programs while cross compiling
+@end example
+
+This means that you have something wrong with your compiler installation!
+In this case you should upgrade your compiler to a newer version. You may
+also be able to solve this problem by inserting the following row into the
+@code{config.cache} file:
+
+@example
+ac_cv_sys_restartable_syscalls=$@{ac_cv_sys_restartable_syscalls='no'@}
+@end example
+
+If you are using Solaris on a SPARC, the recommended compiler is
+@code{gcc} 2.95.2. You can find this at @uref{http://gcc.gnu.org/}.
+Note that @code{egs} 1.1.1 and @code{gcc} 2.8.1 don't work reliably on
+SPARC!
+
+The recommended @code{configure} line when using @code{gcc} 2.95.2 is:
+
+@example
+shell> CC=gcc CFLAGS="-O6" \
+ CXX=gcc CXXFLAGS="-O6 -felide-constructors -fno-exceptions -fno-rtti" \
+ ./configure --prefix=/usr/local/mysql --with-low-memory
+@end example
+
+If you have the Sun Workshop 4.2 compiler, you can run @code{configure} like
+this:
+
+CC=cc CFLAGS="-xstrconst -Xa -xO4 -native -mt" CXX=CC CXXFLAGS="-xO4 -native -noex -mt" ./configure --prefix=/usr/local/mysql
+
+@example
+shell> CC=cc CFLAGS="-Xa -fast -xO4 -native -xstrconst -mt" \
+ CXX=CC CXXFLAGS="-noex -XO4 -mt" \
+ ./configure
+@end example
+
+You may also have to edit the @code{configure} script to change this line:
+
+@example
+#if !defined(__STDC__) || __STDC__ != 1
+@end example
+
+to this:
+
+@example
+#if !defined(__STDC__)
+@end example
+
+If you turn on @code{__STDC__} with the @code{-Xc} option, the Sun compiler
+can't compile with the Solaris @file{pthread.h} header file. This is a Sun
+bug (broken compiler or broken include file).
+
+If @code{mysqld} issues the error message shown below when you run it, you have
+tried to compile @strong{MySQL} with the Sun compiler without enabling the
+multi-thread option (@code{-mt}):
+
+@example
+libc internal error: _rmutex_unlock: rmutex not held
+@end example
+
+Add @code{-mt} to @code{CFLAGS} and @code{CXXFLAGS} and try again.
+
+If you get the following error when compiling @strong{MySQL} with @code{gcc},
+it means that your @code{gcc} is not configured for your version of Solaris!
+
+@example
+shell> gcc -O3 -g -O2 -DDBUG_OFF -o thr_alarm ...
+./thr_alarm.c: In function `signal_hand':
+./thr_alarm.c:556: too many arguments to function `sigwait'
+@end example
+
+The proper thing to do in this case is to get the newest version of
+@code{gcc} and compile it with your current @code{gcc} compiler! At
+least for Solaris 2.5, almost all binary versions of @code{gcc} have
+old, unusable include files that will break all programs that use
+threads (and possibly other programs)!
+
+Solaris doesn't provide static versions of all system libraries
+(@code{libpthreads} and @code{libdl}), so you can't compile @strong{MySQL}
+with @code{--static}. If you try to do so, you will get the error:
+
+@example
+ld: fatal: library -ldl: not found
+@end example
+
+If too many processes try to connect very rapidly to @code{mysqld}, you will
+see this error in the @strong{MySQL} log:
+
+@example
+Error in accept: Protocol error
+@end example
+
+You might try starting the server with the @code{--set-variable back_log=50}
+option as a workaround for this. @xref{Command-line options}.
+
+If you are linking your own @strong{MySQL} client, you might get the
+following error when you try to execute it:
+
+@example
+ld.so.1: ./my: fatal: libmysqlclient.so.#: open failed: No such file or directory
+@end example
+
+The problem can be avoided by one of the following methods:
+
+@itemize @bullet
+@item
+Link the client with the following flag (instead of @code{-Lpath}):
+@code{-Wl,r/full-path-to-libmysqlclient.so}.
+@item
+Copy @code{libmysqclient.so} to @file{/usr/lib}.
+@item
+@tindex LD_RUN_PATH environment variable
+@tindex Environment variable, LD_RUN_PATH
+Add the pathname of the directory where @code{libmysqlclient.so} is located
+to the @code{LD_RUN_PATH} environment variable before running your client.
+@end itemize
+
+When using the @code{--with-libwrap} configure option, you must also
+include the libraries that @code{libwrap.a} needs:
+
+@example
+--with-libwrap="/opt/NUtcpwrapper-7.6/lib/libwrap.a -lnsl -lsocket
+@end example
+
+If you have problems with that configure or @strong{MySQL} tries to link
+with @code{-lz} and you don't have this installed, you have two options:
+
+@itemize @bullet
+@item
+If you want to be able to use the compressed communication protocol,
+you need to get and install zlib from ftp.gnu.org.
+@item
+Configure with @code{--with-named-z-libs=no}
+@end itemize
+
+If you are using gcc and have problems with loading @code{UDF} functions
+into @code{MySQL}, try adding @code{-lgcc} to the link line for the
+@code{UDF} function.
+
+@node Solaris 2.7, Solaris x86, Solaris, Source install system issues
+@subsection Solaris 2.7 / 2.8 notes
+
+You can normally use a Solaris 2.6 binary on Solaris 2.7 and 2.8. Most
+of the Solaris 2.6 issues also apply for Solaris 2.7 and 2.8.
+
+Note that @strong{MySQL} 3.23.4 and above should be able to autodetect
+new versions of Solaris and enable workarounds for the following
+problems!
+
+Solaris 2.7 / 2.8 has some bugs in the include files. You may see the
+following error when you use @code{gcc}:
+
+@example
+/usr/include/widec.h:42: warning: `getwc' redefined
+/usr/include/wchar.h:326: warning: this is the location of the previous
+definition
+@end example
+
+If this occurs, you can do the following to fix the problem:
+
+Copy @code{/usr/include/widec.h} to
+@code{.../lib/gcc-lib/os/gcc-version/include} and change line 41 from:
+
+@example
+#if !defined(lint) && !defined(__lint)
+
+to
+
+#if !defined(lint) && !defined(__lint) && !defined(getwc)
+@end example
+
+Alternatively, you can edit @file{/usr/include/widec.h} directly. Either
+way, after you make the fix, you should remove @file{config.cache} and run
+@code{configure} again!
+
+If you get errors like this when you run @code{make}, it's because @code{configure}
+didn't detect the @file{curses.h} file (probably because of the error in
+@code{/usr/include/widec.h}:
+
+@example
+In file included from mysql.cc:50:
+/usr/include/term.h:1060: syntax error before `,'
+/usr/include/term.h:1081: syntax error before `;'
+@end example
+
+The solution to this is to do one of the following steps:
+
+@itemize @bullet
+@item
+Edit @file{/usr/include/widec.h} as indicted above and rerun configure
+@item
+Remove the @code{#define HAVE_TERM} line from @file{config.h} file and
+run @code{make} again.
+@item
+Configure with @code{CFLAGS=-DHAVE_CURSES CXXFLAGS=-DHAVE_CURSES ./configure}
+@end itemize
+
+@node Solaris x86, SunOS, Solaris 2.7, Source install system issues
+@subsection Solaris x86 notes
+
+If you are using @code{gcc} or @code{egcs} on Solaris x86 and you
+experience problems with core dumps under load, you should use the
+following @code{configure} command:
+
+@example
+shell> CC=gcc CFLAGS="-O6 -fomit-frame-pointer" \
+ CXX=gcc \
+ CXXFLAGS="-O6 -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" \
+ ./configure --prefix=/usr/local/mysql
+@end example
+
+This will avoid problems with the @code{libstdc++} library and with C++
+exceptions.
+
+If this doesn't help, you should compile a debug version and run
+it with a trace file or under @code{gdb}. @xref{Debugging server}.
+
+@node SunOS, Linux, Solaris x86, Source install system issues
+@subsection SunOS 4 notes
+
+On SunOS 4, MIT-pthreads is needed to compile @strong{MySQL}, which in turn
+means you will need GNU @code{make}.
+
+Some SunOS 4 systems have problems with dynamic libraries and
+@code{libtool}. You can use the following @code{configure} line to avoid
+this problem:
+
+@example
+shell> ./configure --disable-shared --with-mysqld-ldflags=-all-static
+@end example
+
+When compiling @code{readline}, you may get warnings about duplicate defines.
+These may be ignored.
+
+When compiling @code{mysqld}, there will be some @code{implicit declaration
+of function} warnings. These may be ignored.
+
+@node Linux, Alpha-DEC-Unix, SunOS, Source install system issues
+@subsection Linux notes (all Linux versions)
+
+@strong{MySQL} uses LinuxThreads on Linux. If you are using an old Linux
+version that doesn't have @code{glibc2}, you must install LinuxThreads before
+trying to compile
+@strong{MySQL}. @uref{http://www.mysql.com/Downloads/Linux}
+
+Note that @code{glibc} versions before and including 2.1.1 has a fatal
+bug in @code{pthread_mutex_timedwait} handling, which is used when you
+do @code{INSERT DELAYED}. If you are using @code{INSERT DELAYED}, you
+@strong{MUST} add the following patch to your glibc library:
+@uref{http://www.mysql.com/Downloads/Patches/glibc-pthread_cond_timedwait.patch}.
+@strong{MySQL} 3.23.7 and the @strong{MySQL} 3.22.32 contains a
+temporary workaround for this bug.
+
+If you plan to have 1000+ concurrent connections, you will need to make
+some changes to LinuxThreads, recompile it, and re-link MySQL against
+the new libpthread.a . Increase PTHREAD_THREADS_MAX in
+sysdeps/unix/sysv/linux/bits/local_lim.h to 4096 and decrease STACK_SIZE
+in internals.h to 256 KB . Note that MySQL will not be stable with
+around 1000 connections if STACK_SIZE is the default of 2 MB.
+
+If you have glibc 2.1.3-65 or newer, you don't have to increase STACK_SIZE;
+You can instead just change the @code{thread_stack} value for @code{mysqld}.
+
+If you use a lot of concurrent connections, you may suffer from a 2.2
+kernel "feature" that penalizes a process for forking or cloning a child
+in an attempt to prevent a fork bomb attack. This will cause MySQL not
+to scale well as you increase the number of concurrent clients. On
+single CPU systems, we have seen this manifested in a very slow thread
+creation - which means it may take a long time to connect to MySQL ( as
+long as 1 minute), and it may take just as long to shut it down. On
+multiple CPU systems, we have observed a gradual drop in query speed as
+the number of clients increases. In the process of trying to find a
+solution, we have received a kernel patch from one of our users, who
+claimed it made a lot of difference for his site. We have done some
+limited testing in which the patch greatly improved the scalabitility of
+MySQL. The patch is available
+@uref{http://www.mysql.com/Downloads/Patches/linux-fork.patch,here} - be
+warned, though, that we assume no reponsibility for any damage that this
+patch could do - use at your own risk. We have also been told by the
+Linux kernel developers that this problem is fixed in 2.4, although we
+have not yet done any testing.
+
+If you can't start @code{mysqld} or if @code{mysql_install_db} doesn't work,
+please continue reading! This only happens on Linux system with problems in
+the LinuxThreads or @code{libc}/@code{glibc} libraries. There are a lot of
+simple workarounds to get @strong{MySQL} to work! The simplest is to use the
+binary version of @strong{MySQL} (not the RPM) for Linux x86. One nice
+aspect of this version is that it's probably 10% faster than any version you
+would compile yourself! @xref{Compile and link options}.
+
+One known problem with the binary distribution is that with older Linux
+systems that use @code{libc} (like RedHat 4.x or Slackware), you will get
+some non-fatal problems with hostname resolution
+@xref{Binary notes-Linux}.
+
+@code{myisamchk} hangs with @code{libc.so.5.3.12}. Upgrading to the newest
+@code{libc} fixes this problem.
+
+When using LinuxThreads you will see a minimum of three processes
+running. These are in fact threads. There will be one thread for the
+LinuxThreads manager, one thread to handle connections, and one thread
+to handle alarms and signals.
+
+Note that the linux kernel and the linuxthread library can by default
+only have 1024 threads. This means that you can only have up to 1021
+connections to MySQL on a unpatched system. The page
+@uref{http://www.volano.com/linuxnotes.html} contains information how to
+go around this limit.
+
+If you see a dead @code{mysqld} daemon process with @code{ps}, this usually
+means that you have found a bug in @strong{MySQL} or you have got a corrupted
+table. @xref{Crashing}.
+
+If you are using LinuxThreads and @code{mysqladmin shutdown} doesn't work,
+you must upgrade to LinuxThreads 0.7.1 or newer.
+
+If you are using RedHat, you might get errors like this:
+
+@example
+/usr/bin/perl is needed...
+/usr/sh is needed...
+/usr/sh is needed...
+@end example
+
+If so, you should upgrade your version of @code{rpm} to
+@file{rpm-2.4.11-1.i386.rpm} and @file{rpm-devel-2.4.11-1.i386.rpm} (or later).
+
+You can get the upgrades of libraries to RedHat 4.2 from
+@uref{ftp://ftp.redhat.com/updates/4.2/i386}. Or
+@uref{http://www.sunsite.unc.edu/pub/Linux/distributions/redhat/code/rpm/}
+for other distributions.
+
+If you are linking your own @strong{MySQL} client and get the error:
+
+@example
+ld.so.1: ./my: fatal: libmysqlclient.so.4: open failed: No such file or directory
+@end example
+
+when executing them, the problem can be avoided by one of the following
+methods:
+
+@itemize @bullet
+@item
+Link the client with the following flag (instead of @code{-Lpath}):
+@code{-Wl,r/path-libmysqlclient.so}.
+@item
+Copy @code{libmysqclient.so} to @file{/usr/lib}.
+@item
+@tindex LD_RUN_PATH environment variable
+@tindex Environment variable, LD_RUN_PATH
+Add the pathname of the directory where @code{libmysqlclient.so} is located
+to the @code{LD_RUN_PATH} environment variable before running your client.
+@end itemize
+
+If you are using the Fujitsu compiler @code{(fcc / FCC)} you will have
+some problems compiling @strong{MySQL} because the Linux header files are very
+@code{gcc} oriented.
+
+The following @code{configure} line should work with @code{fcc/FCC}:
+
+@example
+CC=fcc CFLAGS="-O -K fast -K lib -K omitfp -Kpreex -D_GNU_SOURCE -DCONST=const -DNO_STRTOLL_PROTO" CXX=FCC CXXFLAGS="-O -K fast -K lib -K omitfp -K preex --no_exceptions --no_rtti -D_GNU_SOURCE -DCONST=const -Dalloca=__builtin_alloca -DNO_STRTOLL_PROTO '-D_EXTERN_INLINE=static __inline'" ./configure --prefix=/usr/local/mysql --enable-assembler --with-mysqld-ldflags=-all-static --disable-shared --with-low-memory
+@end example
+
+@menu
+* Linux-x86:: Linux-x86 notes
+* Linux-RedHat50:: RedHat 5.0 notes
+* Linux-RedHat51:: RedHat 5.1 notes
+* Linux-SPARC:: Linux-SPARC notes
+* Linux-Alpha:: Linux-Alpha notes
+* MKLinux:: MkLinux notes
+* Qube2:: Qube2 Linux notes
+* Linux-Ia64::
+@end menu
+
+@node Linux-x86, Linux-RedHat50, Linux, Linux
+@subsubsection Linux-x86 notes
+
+@strong{MySQL} requires @code{libc} version 5.4.12 or newer. It's known to
+work with @code{libc} 5.4.46. @code{glibc} version 2.0.6 and later should
+also work. There have been some problems with the @code{glibc} RPMs from
+RedHat so if you have problems, check whether or not there are any updates!
+The @code{glibc} 2.0.7-19 and 2.0.7-29 RPMs are known to work.
+
+On some older Linux distributions, @code{configure} may produce an error
+like this:
+
+@example
+Syntax error in sched.h. Change _P to __P in the /usr/include/sched.h file.
+See the Installation chapter in the Reference Manual.
+@end example
+
+Just do what the error message says and add an extra underscore to the
+@code{_P} macro that has only one underscore, then try again.
+
+You may get some warnings when compiling; those shown below can be ignored:
+
+@example
+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'
+@end example
+
+In Debian GNU/Linux, if you want @strong{MySQL} to start automatically when
+the system boots, do the following:
+
+@example
+shell> cp support-files/mysql.server /etc/init.d/mysql.server
+shell> /usr/sbin/update-rc.d mysql.server defaults 99
+@end example
+
+@code{mysql.server} can be found in the @file{share/mysql} directory
+under the @strong{MySQL} installation directory, or in the
+@file{support-files} directory of the @strong{MySQL} source tree.
+
+If @code{mysqld} always core dumps when it starts up, the problem may be that
+you have an old @file{/lib/libc.a}. Try renaming it, then remove
+@file{sql/mysqld} and do a new @code{make install} and try again. This
+problem has been reported on some Slackware installations. RedHat 5.0 has
+also a similar problem with some new @code{glibc} versions.
+@xref{Linux-RedHat50}.
+
+If you get the following error when linking @code{mysqld},
+it means that your @file{libg++.a} is not installed correctly:
+
+@example
+/usr/lib/libc.a(putc.o): In function `_IO_putc':
+putc.o(.text+0x0): multiple definition of `_IO_putc'
+@end example
+
+You can avoid using @file{libg++.a} by running @code{configure} like this:
+
+@example
+shell> CXX=gcc ./configure
+@end example
+
+@node Linux-RedHat50, Linux-RedHat51, Linux-x86, Linux
+@subsubsection RedHat 5.0 notes
+
+If you have any problems with @strong{MySQL} on RedHat, you should start by
+upgrading @code{glibc} to the newest possible version!
+
+If you install all the official RedHat patches (including
+@code{glibc-2.0.7-19} and @code{glibc-devel-2.0.7-19}), both the
+binary and source distributions of @strong{MySQL} should work without
+any trouble!
+
+The updates are needed because there is a bug in @code{glibc} 2.0.5 in how
+@code{pthread_key_create} variables are freed. With @code{glibc} 2.0.5, you
+must use a statically-linked @strong{MySQL} binary distribution. If you
+want to compile from source, you must install the corrected version of
+LinuxThreads from @uref{http://www.mysql.com/Downloads/Linux} or upgrade your
+@code{glibc}.
+
+If you have an incorrect version of @code{glibc} or LinuxThreads, the symptom
+is that @code{mysqld} crashes after each connection. For example,
+@code{mysqladmin version} will crash @code{mysqld} when it finishes!
+
+Another symptom of incorrect libraries is that @code{mysqld} crashes at
+once when it starts. On some Linux systems, this can be fixed by configuring
+like this:
+
+@example
+shell> ./configure --with-mysqld-ldflags=-all-static
+@end example
+
+On Redhat 5.0, the easy way out is to install the @code{glibc} 2.0.7-19 RPM
+and run @code{configure} @strong{without} the
+@code{--with-mysqld-ldflags=-all-static} option.
+
+For the source distribution of @code{glibc} 2.0.7, a patch that is easy to
+apply and is tested with @strong{MySQL} may be found at:
+@example
+@uref{http://www.mysql.com/Download/Linux/glibc-2.0.7-total-patch.tar.gz}
+@end example
+
+If you experience crashes like these when you build @strong{MySQL}, you can
+always download the newest binary version of @strong{MySQL}. This is
+statically-linked to avoid library conflicts and should work on all Linux
+systems!
+
+@strong{MySQL} comes with an internal debugger that can generate
+trace files with a lot of information that can be used to find and solve a
+wide range of different problems.
+@xref{Debugging server}.
+
+@node Linux-RedHat51, Linux-SPARC, Linux-RedHat50, Linux
+@subsubsection RedHat 5.1 notes
+
+The @code{glibc} of RedHat 5.1 (@code{glibc} 2.0.7-13) has a memory leak, so
+to get a stable @strong{MySQL} version, you must upgrade @code{glibc} to
+2.0.7-19, downgrade @code{glibc} or use a binary version of @code{mysqld}. If
+you don't do this, you will encounter memory problems (out of memory, etc.,
+etc.). The most common error in this case is:
+
+@example
+Can't create a new thread (errno 11). If you are not out of available
+memory, you can consult the manual for any possible OS dependent bug
+@end example
+
+After you have upgraded to @code{glibc} 2.0.7-19, you can configure
+@strong{MySQL} with dynamic linking (the default), but you @strong{cannot}
+run @code{configure} with the @code{--with-mysqld-ldflags=-all-static} option
+until you have installed @code{glibc} 2.0.7-19 from source!
+
+You can check which version of @code{glibc} you have with @code{rpm -q glibc}.
+
+@node Linux-SPARC, Linux-Alpha, Linux-RedHat51, Linux
+@subsubsection Linux-SPARC notes
+
+In some implementations, @code{readdir_r()} is broken. The symptom is that
+@code{SHOW DATABASES} always returns an empty set. This
+can be fixed by removing @code{HAVE_READDIR_R} from @file{config.h} after
+configuring and before compiling.
+
+Some problems will require patching your Linux installation. The patch can
+be found at
+@uref{http://www.mysql.com/Downloads/patches/Linux-sparc-2.0.30.diff}. This patch is
+against the Linux distribution @file{sparclinux-2.0.30.tar.gz} that is
+available at @code{vger.rutgers.edu} (a version of Linux that was
+never merged with the official 2.0.30). You must also install
+LinuxThreads 0.6 or newer.
+
+Thanks to @email{jacques@@solucorp.qc.ca} for this information.
+
+@node Linux-Alpha, MKLinux, Linux-SPARC, Linux
+@subsubsection Linux-Alpha notes
+
+@strong{MySQL} 3.23.12 is the first @strong{MySQL} version that is
+tested on Linux-Alpha. If you plan to use @strong{MySQL} on
+Linux-Alpha, you should ensure that you have this version or newer.
+
+We have tested @strong{MySQL} on Alpha with our benchmarks + test suite and
+it appears to work nicely. The main thing we haven't yet had time to test
+is how things works with many concurrent users.
+
+When we compiled @strong{MySQL} we where using SuSE 6.3, kernel 2.2.13-SMP,
+egcs 1.1.2 and libc-2.1.2-28.
+
+We used the following configure line:
+
+@example
+CFLAGS="-O6 -fomit-frame-pointer" CXX=gcc CXXFLAGS="-O6 -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --disable-shared
+@end example
+
+If you have access to Compaq's C compiler, the following configure line
+will give you about 9 % more performance:
+@example
+CC=ccc CFLAGS="-fast -O3 -fomit-frame-pointer" CXX=gcc CXXFLAGS="-O6 -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti -mcpu=ev6 -Wa,-mev6" CXXLDFLAGS='/usr/lib/compaq/libots-2.2.7/libots.so /usr/lib/compaq/cpml-5.0.0/libcpml_ev6.a' ./configure --prefix=/usr/local/mysql --disable-shared
+@end example
+
+Note that the last example assumes your are using an Alpha EV6 processor.
+
+Some known problems when running @strong{MySQL} on Linux-Alpha:
+
+@itemize @bullet
+@item
+If you create many files ( > 10000) in one directory (as done by the
+@code{test-create} in the @strong{MySQL} benchmarks, mysqld may report
+the error @code{Can't create/write to file '...' (Errcode: 12)}. This
+is probably a bug in the Linux-Alpha kernel.
+@item
+Debugging threaded applications like @strong{MySQL} will not work with
+@code{gdb 4.18}. You should download and use gdb 5.0 instead!
+@item
+If you try linking mysqld staticly, the resulting image will core dump
+at start. In other words, @strong{DON'T} use
+@code{--with-mysqld-ldflags=-all-static}
+@end itemize
+
+We don't yet know if the following old information is still relevant, so we
+leave this here until we have had time to test Linux-Alpha properly.
+
+If you have problems with signals (@strong{MySQL} dies unexpectedly
+under high load) you may have found an OS bug with threads and
+signals. In this case you can tell @strong{MySQL} not to use signals by
+configuring with:
+
+@example
+shell> CFLAGS=-DDONT_USE_THR_ALARM \
+ CXXFLAGS=-DDONT_USE_THR_ALARM \
+ ./configure ...
+@end example
+
+This doesn't affect the performance of @strong{MySQL}, but has the side
+effect that you can't kill clients that are ``sleeping'' on a connection with
+@code{mysqladmin kill} or @code{mysqladmin shutdown}. Instead, the client
+will die when it issues its next command.
+
+@node MKLinux, Qube2, Linux-Alpha, Linux
+@subsubsection MkLinux notes
+
+@strong{MySQL} should work on MkLinux with the newest @code{glibc} package
+(tested with @code{glibc} 2.0.7).
+
+@node Qube2, Linux-Ia64, MKLinux, Linux
+@subsubsection Qube2 Linux notes
+
+To get @strong{MySQL} to work on Qube2, (Linux Mips), you need the
+newest @code{glibc} libraries (@code{glibc-2.0.7-29C2} is known to
+work). You must also use the @code{egcs} C++ compiler
+(@code{egcs-1.0.2-9}, @code{gcc 2.95.2} or newer).
+
+
+@node Linux-Ia64, , Qube2, Linux
+@subsubsection Linux Ia64 notes
+
+To get @code{MySQL} to compile on Linux Ia64, we had to do the following
+(we assume that this will be easier when next gcc version for ia64 is
+released).
+
+Using @code{gcc-2.9-final}:
+
+@example
+CFLAGS="-O2" CXX=gcc CXXFLAGS="-O2 -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --enable-assembler --with-mysqld-ldflags=-all-static --disable-shared --with-extra-charsets=complex
+@end example
+
+After this you have to edit @file{config.h} and remove the
+@code{HAVE_ATOMIC_ADD} line.
+
+After @code{make} you will get an error that @code{sql/opt_range.cc}
+will not compile (internal compiler error). To fix this, go to the sql
+directory and type @code{make} again. Copy the compile line, but change
+-O2 to -O0. The file should now compile.
+
+Now you can do:
+@example
+cd ..
+make
+make_install
+@end example
+
+and @strong{mysqld} should be ready to run.
+
+@node Alpha-DEC-Unix, Alpha-DEC-OSF1, Linux, Source install system issues
+@subsection Alpha-DEC-Unix notes
+
+When compiling threaded programs under Digital UNIX, the documentation
+recommends using the @code{-pthread} option for @code{cc} and @code{cxx} and
+the libraries @code{-lmach -lexc} (in addition to @code{-lpthread}). You
+should run @code{configure} something like this:
+
+@example
+shell> CC="cc -pthread" CXX="cxx -pthread -O" \
+ ./configure --with-named-thread-libs="-lpthread -lmach -lexc -lc"
+@end example
+
+When compiling @code{mysqld}, you may see a couple of warnings like this:
+
+@example
+mysqld.cc: In function void handle_connections()':
+mysqld.cc:626: passing long unsigned int *' as argument 3 of
+accept(int,sockadddr *, int *)'
+@end example
+
+You can safely ignore these warnings. They occur because @code{configure}
+can detect only errors, not warnings.
+
+If you start the server directly from the command line, you may have problems
+with it dying when you log out. (When you log out, your outstanding processes
+receive a @code{SIGHUP} signal.) If so, try starting the server like this:
+
+@example
+shell> nohup mysqld [options] &
+@end example
+
+@code{nohup} causes the command following it to ignore any @code{SIGHUP}
+signal sent from the terminal. Alternatively, start the server by running
+@code{safe_mysqld}, which invokes @code{mysqld} using @code{nohup} for you.
+
+@node Alpha-DEC-OSF1, SGI-Irix, Alpha-DEC-Unix, Source install system issues
+@subsection Alpha-DEC-OSF1 notes
+
+If you have problems compiling and have DEC @code{CC} and @code{gcc}
+installed, try running @code{configure} like this:
+
+@example
+shell> CC=cc CFLAGS=-O CXX=gcc CXXFLAGS=-O3 \
+ ./configure --prefix=/usr/local/mysql
+@end example
+
+If you get problems with the @file{c_asm.h} file, you can create and use
+a 'dummy' @file{c_asm.h} file with:
+
+@example
+shell> touch include/c_asm.h
+shell> CC=gcc CFLAGS=-I./include \
+ CXX=gcc CXXFLAGS=-O3 \
+ ./configure --prefix=/usr/local/mysql
+@end example
+
+Note that the following problems with the @code{ld} program can be fixed
+by downloading the latest DEC (Compaq) patch kit from:
+@uref{http://ftp.support.compaq.com/public/unix/}.
+
+On OSF1 V4.0D and compiler "DEC C V5.6-071 on Digital UNIX V4.0 (Rev. 878)"
+the compiler had some strange behavior (undefined @code{asm} symbols).
+@code{/bin/ld} also appears to be broken (problems with @code{_exit
+undefined} errors occuring while linking @code{mysqld}). On this system, we
+have managed to compile @strong{MySQL} with the following @code{configure}
+line, after replacing @code{/bin/ld} with the version from OSF 4.0C:
+
+@example
+shell> CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql
+@end example
+
+With the Digital compiler "C++ V6.1-029", the following should work:
+
+@example
+CC=cc -pthread
+CFLAGS=-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all -arch host
+CXX=cxx -pthread
+CXXFLAGS=-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all -arch host
+export CC CFLAGS CXX CXXFLAGS
+./configure --prefix=/usr/mysql/mysql --with-low-memory --enable-large-files --with-mysqld-ldflags=-all-static --disable-shared --with-named-thread-libs="-lmach -lexc -lc"
+@end example
+
+In some versions of OSF1, the @code{alloca()} function is broken. Fix
+this by removing the line in @file{config.h} that defines @code{'HAVE_ALLOCA'}.
+
+The @code{alloca()} function also may have an incorrect prototype in
+@code{/usr/include/alloca.h}. This warning resulting from this can be ignored.
+
+@code{configure} will use the following thread libraries automatically:
+@code{--with-named-thread-libs="-lpthread -lmach -lexc -lc"}.
+
+When using @code{gcc}, you can also try running @code{configure} like this:
+
+@example
+shell> CFLAGS=-D_PTHREAD_USE_D4 CXX=gcc CXXFLAGS=-O3 ./configure ....
+@end example
+
+If you have problems with signals (@strong{MySQL} dies unexpectedly
+under high load) you may have found an OS bug with threads and
+signals. In this case you can tell @strong{MySQL} not to use signals by
+configuring with:
+
+@example
+shell> CFLAGS=-DDONT_USE_THR_ALARM \
+ CXXFLAGS=-DDONT_USE_THR_ALARM \
+ ./configure ...
+@end example
+
+This doesn't affect the performance of @strong{MySQL}, but has the side
+effect that you can't kill clients that are ``sleeping'' on a connection with
+@code{mysqladmin kill} or @code{mysqladmin shutdown}. Instead, the client
+will die when it issues its next command.
+
+With @code{gcc} 2.95.2, you will probably run into the following compile error:
+
+@example
+sql_acl.cc:1456: Internal compiler error in `scan_region', at except.c:2566
+Please submit a full bug report.
+@end example
+
+To fix this you should change to the @code{sql} directory and do a 'cut
+and paste' of the last @code{gcc} line, but change @code{-O3} to @code{-O0} (or add
+@code{-O0} immediately after @code{gcc} if you don't have any @code{-O}
+option on your compile line. After this is done you can just change back to
+the top level directly and run @code{make} again.
+
+@node SGI-Irix, FreeBSD, Alpha-DEC-OSF1, Source install system issues
+@subsection SGI-Irix notes
+
+If you are using Irix 6.5.3 or newer @code{mysqld} will only be able to
+create threads if you run it as a user with @code{CAP_SCHED_MGT}
+privileges (like @code{root}) or give the @code{mysqld} server this privilege
+with the following shell command:
+
+@example
+shell> chcap "CAP_SCHED_MGT+epi" /opt/mysql/libexec/mysqld
+@end example
+
+You may have to undefine some things in @file{config.h} after running
+@code{configure} and before compiling.
+
+In some Irix implementations, the @code{alloca()} function is broken. If the
+@code{mysqld} server dies on some @code{SELECT} statements, remove the lines
+from @file{config.h} that define @code{HAVE_ALLOC} and @code{HAVE_ALLOCA_H}.
+If @code{mysqladmin create} doesn't work, remove the line from
+@file{config.h} that defines @code{HAVE_READDIR_R}. You may have to remove
+the @code{HAVE_TERM_H} line as well.
+
+SGI recommends that you install all of the patches on this page as a set:
+http://support.sgi.com/surfzone/patches/patchset/6.2_indigo.rps.html
+
+At the very minimum, you should install the latest kernel rollup, the
+latest @code{rld} rollup, and the latest @code{libc} rollup.
+
+You definately need all the POSIX patches on this page, for pthreads support:
+
+http://support.sgi.com/surfzone/patches/patchset/6.2_posix.rps.html
+
+If you get the something like the following error when compiling
+@file{mysql.cc}:
+
+@example
+"/usr/include/curses.h", line 82: error(1084): invalid combination of type
+@end example
+
+Then type the following in the top-level directory of your @strong{MySQL}
+source tree:
+
+@example
+shell> extra/replace bool curses_bool < /usr/include/curses.h > include/curses.h
+shell> make
+@end example
+
+There have also been reports of scheduling problems. If only one thread is
+running, things go slow. Avoid this by starting another client. This may lead
+to a 2-to-10-fold increase in execution speed thereafter for the other
+thread. This is a poorly-understood problem with Irix threads; you may have
+to improvise to find solutions until this can be fixed.
+
+If you are compiling with @code{gcc}, you can use the following
+@code{configure} command:
+
+@example
+shell> CC=gcc CXX=gcc CXXFLAGS=-O3 \
+ ./configure --prefix=/usr/local/mysql --with-thread-safe-client --with-named-thread-libs=-lpthread
+@end example
+
+@node FreeBSD, NetBSD, SGI-Irix, Source install system issues
+@subsection FreeBSD notes
+
+FreeBSD 3.x is recommended for running @strong{MySQL} since it the thread package
+is much more integrated.
+
+The easiest and therefor the preferred way to install is to use the
+mysql-server and mysql-client ports available on
+@uref{http://www.freebsd.org}
+
+Using these gives you:
+@itemize @bullet
+@item
+A working @strong{MySQL} with all optimizations known to work on your version
+of FreeBSD enabled.
+@item
+Automatic configuration and build.
+@item
+Startup scripts installed in /usr/local/etc/rc.d
+@item
+Ability to see which files that are installed with pkg_info -L. And to
+remove them all with pkg_delete if you no longer want @strong{MySQL} on that
+machine.
+@end itemize
+
+It is recomended to use MIT-pthreads on FreeBSD 2.x and native threads on
+versions 3 and up. It is possible to run with with native threads on some late
+2.2.x versions but you may encounter problems shutting down mysqld.
+
+Be sure to have your name resolver setup correct. Otherwise you may
+experience resolver delays or failures when connecting to mysqld.
+
+Make sure that the @code{localhost} entry in the @file{/etc/hosts} file is
+correct (otherwise you will have problems connecting to the database). The
+@file{/etc/hosts} file should start with a line:
+
+@example
+127.0.0.1 localhost localhost.your.domain
+@end example
+
+If you notice that @code{configure} will use MIT-pthreads, you should read
+the MIT-pthreads notes. @xref{MIT-pthreads}.
+
+If you get an error from @code{make install} that it can't find
+@file{/usr/include/pthreads}, @code{configure} didn't detect that you need
+MIT-pthreads. This is fixed by executing these commands:
+
+@example
+shell> rm config.cache
+shell> ./configure --with-mit-threads
+@end example
+
+The behavior of FreeBSD @code{make} is slightly different from that of GNU
+@code{make}. If you have @code{make}-related problems, you should install GNU
+@code{make}.
+
+FreeBSD is also known to have a very low default file handle limit.
+@xref{Not enough file handles}. Uncomment the ulimit -n section in
+safe_mysqld or raise the limits for the mysqld user in /etc/login.conf
+(and rebuild it witg cap_mkdb /etc/login.conf) also be sure you set the
+appropriate Class for this user in the password file if you are not
+using the default (use: chpass mysqld-user-name)
+
+If you get problems with the current date in @strong{MySQL}, setting the
+@code{TZ} variable will probably help. @xref{Environment variables}.
+
+To get a secure and stable system you should only use FreeBSD kernels
+that are marked @code{-STABLE}
+
+@node NetBSD, OpenBSD, FreeBSD, Source install system issues
+@subsection NetBSD notes
+
+To compile on NetBSD you need GNU @code{make}. Otherwise the compile will crash
+when @code{make} tries to run @code{lint} on C++ files.
+
+@node OpenBSD, BSDI, NetBSD, Source install system issues
+@subsection OpenBSD 2.5 notes
+
+On OpenBSD 2.5, you can compile @strong{MySQL} with native threads with the
+following options:
+
+@example
+CFLAGS=-pthread CXXFLAGS=-pthread ./configure --with-mit-threads=no
+@end example
+
+@node BSDI, SCO, OpenBSD, Source install system issues
+@subsection BSD/OS notes
+
+@menu
+* BSDI2:: BSD/OS 2.x notes
+* BSDI3:: BSD/OS 3.x notes
+* BSDI4:: BSD/OS 4.x notes
+@end menu
+
+@node BSDI2, BSDI3, BSDI, BSDI
+@subsubsection BSD/OS 2.x notes
+
+If you get the following error when compiling @strong{MySQL}, your
+@code{ulimit} value for virtual memory is too low:
+
+@example
+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
+@end example
+
+Try using @code{ulimit -v 80000} and run @code{make} again. If this
+doesn't work and you are using @code{bash}, try switching to @code{csh}
+or @code{sh}; some BSDI users have reported problems with @code{bash}
+and @code{ulimit}.
+
+If you are using @code{gcc}, you may also use have to use the
+@code{--with-low-memory} flag for @code{configure} to be able to compile
+@file{sql_yacc.cc}.
+
+If you get problems with the current date in @strong{MySQL}, setting the
+@code{TZ} variable will probably help. @xref{Environment variables}.
+
+@node BSDI3, BSDI4, BSDI2, BSDI
+@subsubsection BSD/OS 3.x notes
+
+Upgrade to BSD/OS 3.1. If that is not possible, install BSDIpatch M300-038.
+
+Use the following command when configuring @strong{MySQL}:
+
+@example
+shell> env CXX=shlicc++ CC=shlicc2 \
+ ./configure \
+ --prefix=/usr/local/mysql \
+ --localstatedir=/var/mysql \
+ --without-perl \
+ --with-unix-socket-path=/var/mysql/mysql.sock
+@end example
+
+The following is also known to work:
+
+@example
+shell> env CC=gcc CXX=gcc CXXFLAGS=-O3 \
+ ./configure \
+ --prefix=/usr/local/mysql \
+ --with-unix-socket-path=/var/mysql/mysql.sock
+@end example
+
+You can change the directory locations if you wish, or just use the
+defaults by not specifying any locations.
+
+If you have problems with performance under heavy load, try using the
+@code{--skip-thread-priority} option to @code{safe_mysqld}! This will run
+all threads with the same priority; on BSDI 3.1, this gives better
+performance (at least until BSDI fixes their thread scheduler).
+
+If you get the error @code{virtual memory exhausted} while compiling,
+you should try using @code{ulimit -v 80000} and run @code{make} again.
+If this doesn't work and you are using @code{bash}, try switching to
+@code{csh} or @code{sh}; some BSDI users have reported problems with
+@code{bash} and @code{ulimit}.
+
+@node BSDI4, , BSDI3, BSDI
+@subsubsection BSD/OS 4.x notes
+
+BSDI 4.x has some thread related bugs. If you want to use @strong{MySQL}
+on this, you should install all thread related patches. At least
+M400-023 should be installed.
+
+On some BSDI 4.x systems, you may get problems with shared libraries. The
+symptom is that you can't execute any client programs, like for example
+@code{mysqladmin}. In this case you need to reconfigure not to use
+shared libraries with the @code{--disable-shared} option to configure.
+
+@node SCO, SCO Unixware, BSDI, Source install system issues
+@subsection SCO notes
+
+The current port is tested only on a ``sco3.2v5.0.4'' and
+``sco3.2v5.0.5'' system. There has also been a lot of progress on a
+port to ``sco 3.2v4.2''.
+
+For the moment the recommended compiler on OpenServer is gcc 2.95.2. With this
+you should be able to compile @code{MySQL} with just:
+
+@example
+CC=gcc CXX=gcc ./configure ... (options)
+@end example
+
+@enumerate
+@item
+For OpenServer 5.0.X you need to use GDS in Skunkware 95 (95q4c). This
+is necessary because GNU @code{gcc} 2.7.2 in Skunkware 97 does not have
+GNU @code{as}. You can also use @code{egcs} 1.1.2 or newer
+@uref{http://www.egcs.com/}. If you are using @code{egcs} 1.1.2 you have
+to execute the following command:
+
+@example
+shell> cp -p /usr/include/pthread/stdtypes.h /usr/local/lib/gcc-lib/i386-pc-sco3.2v5.0.5/egcs-2.91.66/include/pthread/
+@end example
+@item
+You need the port of GCC 2.5.? for this product and the Development
+system. They are required on this version of SCO UNIX. You cannot
+just use the GCC Dev system.
+@item
+You should get the FSU Pthreads package and install it first. This can be
+found at
+@uref{http://www.cs.wustl.edu/~schmidt/ACE_wrappers/FSU-threads.tar.gz}.
+You can also get a precompiled package from
+@uref{http://www.mysql.com/Downloads/SCO/FSU-threads-3.5c.tar.gz}.
+@item
+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
+Development 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
+without a good port. The port for this product requires the SCO UNIX
+Development system. Without it, you are missing the libraries and the
+linker that is needed.
+@item
+To build FSU Pthreads on your system, do the following:
+@enumerate
+@item
+Run @code{./configure} in the @file{threads/src} directory and select
+the SCO OpenServer option. This command copies @file{Makefile.SCO5} to
+@file{Makefile}.
+@item
+Run @code{make}.
+@item
+To install in the default @file{/usr/include} directory, login as root,
+then @code{cd} to the @file{thread/src} directory, and run @code{make
+install}.
+@end enumerate
+@item
+Remember to use GNU @code{make} when making @strong{MySQL}.
+@item
+On OSR 5.0.5, you should use the following configure line:
+@example
+shell> CC="gcc -DSCO" CXX="gcc -DSCO" ./configure
+@end example
+The @code{-DSCO} is needed to help configure detect some thread
+functions properly. If you forget @code{-DSCO}, you will get the following
+error message while compiling:
+@example
+my_pthread.c: In function `my_pthread_mutex_init':
+my_pthread.c:374: `pthread_mutexattr_default' undeclared (first use this function)
+@end example
+@item
+If you don't start @code{safe_mysqld} as root, you probably will get only the
+default 110 open files per process. @code{mysqld} will write a note about this
+in the log file.
+@item
+With SCO 3.2V5.0.5, you should use FSU Pthreads version 3.5c or newer.
+The following @code{configure} command should work:
+@example
+shell> CC="gcc -belf" ./configure --prefix=/usr/local/mysql --disable-shared
+@end example
+@item
+With SCO 3.2V4.2, you should use FSU Pthreads version 3.5c or newer.
+The following @code{configure} command should work:
+@example
+shell> CFLAGS="-D_XOPEN_XPG4" CXX=gcc CXXFLAGS="-D_XOPEN_XPG4" \
+ ./configure \
+ --with-debug --prefix=/usr/local/mysql \
+ --with-named-thread-libs="-lgthreads -lsocket -lgen -lgthreads" \
+ --with-named-curses-libs="-lcurses"
+@end example
+You may get some problems with some include files. In this case, you can
+find new SCO-specific include files at
+@uref{http://www.mysql.com/Downloads/SCO/SCO-3.2v4.2-includes.tar.gz}.
+You should unpack this file in the @file{include}
+directory of your @strong{MySQL} source tree.
+@end enumerate
+
+SCO development notes:
+
+@itemize @bullet
+@item
+@strong{MySQL} should automatically detect FSU Pthreads and link @code{mysqld}
+with @code{-lgthreads -lsocket -lgthreads}.
+@item
+The SCO development libraries are reentrant in FSU Pthreads. SCO claims
+that its libraries' functions are reentrant, so they must be reentrant with
+FSU Pthreads. FSU Pthreads on OpenServer tries to use the SCO scheme to
+make reentrant library.
+@item
+FSU Pthreads (at least the version at @uref{http://www.mysql.com/}) comes linked with
+GNU @code{malloc}. If you encounter problems with memory usage, make sure that
+@file{gmalloc.o}
+is included in @file{libgthreads.a} and @file{libgthreads.so}.
+@item
+In FSU Pthreads, the following system calls are pthreads-aware: @code{read()},
+@code{write()}, @code{getmsg()}, @code{connect()}, @code{accept()},
+@code{select()} and @code{wait()}.
+@end itemize
+
+If you want to install DBI on SCO, you have to edit the @file{Makefiles} in
+DBI-xxx and each subdirectory:
+
+@example
+OLD: NEW:
+CC = cc CC = gcc -belf
+CCCDLFLAGS = -KPIC -W1,-Bexport CCCDLFLAGS = -fpic
+CCDLFLAGS = -wl,-Bexport CCDLFLAGS =
+
+LD = ld LD = gcc -belf -G -fpic
+LDDLFLAGS = -G -L/usr/local/lib LDDLFLAGS = -L/usr/local/lib
+LDFLAGS = -belf -L/usr/local/lib LDFLAGS = -L/usr/local/lib
+
+LD = ld LD = gcc -belf -G -fpic
+OPTIMISE = -Od OPTIMISE = -O1
+
+OLD:
+CCCFLAGS = -belf -dy -w0 -U M_XENIX -DPERL_SCO5 -I/usr/local/include
+
+NEW:
+CCFLAGS = -U M_XENIX -DPERL_SCO5 -I/usr/local/include
+@end example
+
+This is because the Perl dynaloader will not load the @code{DBI} modules
+if they were compiled with @code{icc} or @code{cc}.
+
+Perl works best when compiled with @code{cc}.
+
+@node SCO Unixware, IBM-AIX, SCO, Source install system issues
+@subsection SCO Unixware 7.0 notes
+
+You must use a version of @strong{MySQL} at least as recent as 3.22.13, because
+that version fixes some portability problems under Unixware.
+
+We have been able to compile @strong{MySQL} with the following @code{configure}
+command on UnixWare 7.0.1:
+
+@example
+shell> CC=cc CXX=CC ./configure --prefix=/usr/local/mysql
+@end example
+
+If you want to use @code{gcc}, you must use @code{gcc} 2.95.2 or newer.
+
+@node IBM-AIX, HP-UX 10.20, SCO Unixware, Source install system issues
+@subsection IBM-AIX notes
+
+Automatic detection of @code{xlC} is missing from Autoconf, so a
+@code{configure} command something like this is needed when compiling
+@strong{MySQL}: (The example uses the IBM compiler)
+
+@example
+shell> CC="xlc_r" CFLAGS="-ma -O3 -qstrict -DHAVE_INT_8_16_32" \
+ CXX="xlC_r" CXXFLAGS="-ma -O3 -qstrict -DHAVE_INT_8_16_32" \
+ ./configure
+@end example
+
+If you change the @code{-O3} to @code{-O2} in the above configure line,
+you must also remove the @code{-qstrict} option (this is a limitation in
+the IBM C compiler).
+
+If you are using @code{gcc} or @code{egcs} to compile @strong{MySQL}, you
+@strong{MUST} use the @code{-fno-exceptions} flag, as the exception
+handling in @code{gcc}/@code{egcs} is not thread-safe! (This is tested with
+@code{egcs} 1.1.) We recommend the following @code{configure} line with
+@code{egcs} and @code{gcc} on AIX:
+
+@example
+shell> CC=gcc \
+ CFLAGS="-DHAVE_INT_8_16_32" \
+ CXX=gcc \
+ CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti -DHAVE_INT_8_16_32" \" \
+ ./configure --prefix=/usr/local/mysql --with-debug --with-low-memory
+@end example
+
+If you have problems with signals (@strong{MySQL} dies unexpectedly
+under high load) you may have found an OS bug with threads and
+signals. In this case you can tell @strong{MySQL} not to use signals by
+configuring with:
+
+@example
+shell> CFLAGS=-DDONT_USE_THR_ALARM CXX=gcc \
+ CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti -DDONT_USE_THR_ALARM" \
+ ./configure --prefix=/usr/local/mysql --with-debug --with-low-memory
+@end example
+
+This doesn't affect the performance of @strong{MySQL}, but has the side
+effect that you can't kill clients that are ``sleeping'' on a connection with
+@code{mysqladmin kill} or @code{mysqladmin shutdown}. Instead, the client
+will die when it issues its next command.
+
+On some versions of AIX, linking with @code{libbind.a} makes @code{getservbyname} core
+dump. This is an AIX bug and should be reported to IBM.
+
+@node HP-UX 10.20, HP-UX 11.x, IBM-AIX, Source install system issues
+@subsection HP-UX 10.20 notes
+
+There are a couple of ``small'' problems when compiling @strong{MySQL} on
+HP-UX. We recommend that you use @code{gcc} instead of the HP-UX native
+compiler, because @code{gcc} produces better code!
+
+We recommend one to use gcc 2.95 on HP-UX. Don't use high optimization
+flags (like -O6) as this may not be safe on HP-UX.
+
+Note that MIT-pthreads can't be compiled with the HP-UX compiler,
+because it can't compile @code{.S} (assembler) files.
+
+The following configure line should work:
+
+@example
+CFLAGS="-DHPUX -I/opt/dce/include" CXXFLAGS="-DHPUX -I/opt/dce/include -felide-constructors -fno-exceptions -fno-rtti" CXX=gcc ./configure --with-pthread --with-named-thread-libs='-ldce' --prefix=/usr/local/mysql --disable-shared
+@end example
+
+If you are compiling @code{gcc} 2.95 yourself, you should NOT link it with
+the DCE libraries (@code{libdce.a} or @code{libcma.a}) if you want to compile
+@strong{MySQL} with MIT-pthreads. If you mix the DCE and MIT-pthreads
+packages you will get a @code{mysqld} to which you cannot connect. Remove
+the DCE libraries while you compile @code{gcc} 2.95!
+
+@node HP-UX 11.x, MacOSX, HP-UX 10.20, Source install system issues
+@subsection HP-UX 11.x notes
+
+For HPUX 11.x we recommend @strong{MySQL} 3.23.15 or later.
+
+If you are using @code{gcc} 2.95.1 on a unpatched HPUX 11.x system you will
+get the error:
+
+@example
+In file included from /usr/include/unistd.h:11,
+ from ../include/global.h:125,
+ from mysql_priv.h:15,
+ from item.cc:19:
+/usr/include/sys/unistd.h:184: declaration of C function `int pthread_atfork(void (*)(...), void (*)
+(...), void (*)(...))' conflicts with
+/usr/include/sys/pthread.h:440: previous declaration `int pthread_atfork(void (*)(), void (*)(), voi
+d (*)())' here
+In file included from item.h:306,
+ from mysql_priv.h:158,
+ from item.cc:19:
+@end example
+
+The problem is that HP-UX doesn't define @code{pthreads_atfork()} consistently.
+It has conflicting prototypes in
+@file{/usr/include/sys/unistd.h}:184 and
+@file{/usr/include/sys/pthread.h}:440 (I post the details below).
+
+One solution is to copy @file{/usr/include/sys/unistd.h} into
+@file{mysql/include} and edit @file{unistd.h} and change it to match
+the definition in @file{pthread.h}. Here's the diff:
+
+@example
+183,184c183,184
+< extern int pthread_atfork(void (*prepare)(), void (*parent)(),
+< void (*child)());
+---
+> extern int pthread_atfork(void (*prepare)(void), void (*parent)(void),
+> void (*child)(void));
+@end example
+
+After this, the following configure line should work:
+
+@example
+CFLAGS="-fomit-frame-pointer -O6 -fpic" CXX=gcc CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti -O6" ./configure --prefix=/usr/local/mysql --disable-shared
+@end example
+
+Here is some information that a HPUX 11.x user sent us about compile
+@strong{MySQL} with HPUX:x compiler
+
+@itemize @bullet
+@item
+@example
+ Environment:
+ proper compilers.
+ setenv CC cc
+ setenv CXX aCC
+ flags
+ setenv CFLAGS -D_REENTRANT
+ setenv CXXFLAGS -D_REENTRANT
+ setenv CPPFLAGS -D_REENTRANT
+ % aCC -V
+ aCC: HP ANSI C++ B3910B X.03.14.06
+ % cc -V /tmp/empty.c
+ cpp.ansi: HP92453-01 A.11.02.00 HP C Preprocessor (ANSI)
+ ccom: HP92453-01 A.11.01.00 HP C Compiler
+ cc: "/tmp/empty.c", line 1: warning 501: Empty source file.
+@end example
+@item
+@example
+ configuration:
+ ./configure --with-pthread \
+ --prefix=/source-control/mysql \
+ --with-named-thread-libs=-lpthread \
+ --with-low-memory
+@end example
+@item
+ added '#define _CTYPE_INCLUDED' to include/m_ctype.h. This
+ symbol is the one defined in HP's /usr/include/ctype.h:
+
+@example
+ /* Don't include std ctype.h when this is included */
+ #define _CTYPE_H
+ #define __CTYPE_INCLUDED
+ #define _CTYPE_INCLUDED
+ #define _CTYPE_USING /* Don't put names in global namespace. */
+@end example
+@item
+I had to use the compile-time flag @code{-D_REENTRANT} to get the
+compiler to recognize the prototype for
+@code{localtime_r}. Alternatively I could have supplied the prototype
+for @code{localtime_r}. But I wanted to catch other bugs without needing
+to run into them. I wasn't sure where I needed it so I added it to all
+flags.
+@item
+The optimization flags used by @strong{MySQL} (-O3) are not recognized
+by HP's compilers. I did not change the flags.
+@end itemize
+
+@node MacOSX, , HP-UX 11.x, Source install system issues
+@subsection MacOS X notes
+
+You can get @strong{MySQL} to work on MacOS X by following the links to
+the MacOS X ports. @xref{Useful Links}.
+
+@strong{MySQL} 3.23.7 should include all patches necessary to configure
+it on MacOSX. You must however first install the pthread package from
+@uref{http://www.prnet.de/RegEx/mysql.html,MySql for MacOSX Server}
+before configuring @strong{MySQL}.
+
+You might want to also add aliases to your shell's resource file to
+access @code{mysql} and @code{mysqladmin} from the command line.
+
+@example
+alias mysql '/usr/local/mysql/bin/mysql'
+alias mysqladmin '/usr/local/mysql/libexec/mysqladmin'
+@end example
+
+@node Win32, OS/2, Source install system issues, Installing
+@section Win32 notes
+
+This section describes installation and use of @strong{MySQL} on Win32. This
+is also described in the @file{README} file that comes with the
+@strong{MySQL} Win32 distribution.
+
+@menu
+* Win32 installation:: Installing @strong{MySQL} on Win32
+* Win95 start:: Starting @strong{MySQL} on Win95 / Win98
+* NT start:: Starting @strong{MySQL} on NT / Win2000
+* Win32 running:: Running @strong{MySQL} on Win32
+* Win32 and SSH:: Connecting to a remote @strong{MySQL} from Win32 with SSH
+* Win32 symbolic links:: Splitting data across different disks under Win32
+* Win32 compiling::
+* Win32 vs Unix:: @strong{MySQL}-Win32 compared to Unix @strong{MySQL}
+@end menu
+
+@node Win32 installation, Win95 start, Win32, Win32
+@subsection Installing MySQL on Win32
+
+If you don't have a registered version of @strong{MySQL}, you should first
+download the shareware version from:
+
+@uref{http://www.mysql.com/mysql_w32.htmy,@strong{MySQL} 3.22.x}
+
+If you plan to connect to @strong{MySQL} from some other program, you will
+probably also need the @strong{MyODBC} driver. You can find this at the
+@uref{http://www.mysql.com/downloads/api-myodbc.html,@strong{MyODBC} download page}.
+
+To install either distribution, unzip it in some empty directory and run the
+@code{Setup.exe} program.
+
+By default, @strong{MySQL}-Win32 is configured to be installed in
+@file{C:\mysql}. If you want to install @strong{MySQL} elsewhere, install it
+in @file{C:\mysql}, then move the installation to where you want it. If you
+do move @strong{MySQL}, you must tell @code{mysqld} where everything is by
+supplying options to @code{mysqld}. Use @code{C:\mysql\bin\mysqld --help} to
+display all options! For example, if you have moved the @strong{MySQL}
+distribution to @file{D:\programs\mysql}, you must start @code{mysqld} with:
+@code{D:\programs\mysql\bin\mysqld --basedir D:\programs\mysql}
+
+With the registered version of @strong{MySQL}, you can also create a
+@file{C:\my.cnf} file that holds any default options for the
+@strong{MySQL} server. Copy the file @file{\mysql\my-xxxxx.cnf} to
+@file{C:\my.cnf} and edit this to suit your setup. Note that you should
+specify all paths with @code{/} instead of @code{\}. If you use
+@code{\}, you need to specify this twice, as @code{\} is the escape
+character in @strong{MySQL}.
+@xref{Option files}.
+
+@node Win95 start, NT start, Win32 installation, Win32
+@subsection Starting MySQL on Win95 / Win98
+
+@strong{MySQL} uses TCP/IP to connect a client to a server. (This will
+allow any machine on your network to connect to your @strong{MySQL}
+server). Because of this, you must install TCP/IP on your machine before
+starting @strong{MySQL}. You can find TCP/IP on your Windows CD-ROM.
+
+Note that if you are using an old Win95 release (for example OSR2), it's
+likely that you have an old Winsock package! @strong{MySQL} requires
+Winsock 2! You can get the newest Winsock from
+@uref{http://www.microsoft.com,Microsoft}. Win98 has as default the new
+Winsock 2 library, so the above doesn't apply for Win98.
+
+There are 2 different @strong{MySQL} servers you can use:
+
+@multitable @columnfractions .15 .85
+@item @code{mysqld} @tab Compiled with full debugging and automatic memory allocation checking
+@item @code{mysqld-opt} @tab Optimized for a Pentium processor.
+@end multitable
+
+Both of the above should work on any Intel processor >= i386.
+
+To start the @code{mysqld} server, you should start an MS-DOS window and type:
+
+@example
+C:\mysql\bin\mysqld
+@end example
+
+This will start @code{mysqld} in the background without a window.
+
+You can kill the @strong{MySQL} server by executing:
+
+@example
+C:\mysql\bin\mysqladmin -u root shutdown
+@end example
+
+Note that Win95/Win98 don't support creation of named pipes. On
+Win95/Win98, you can only use named pipes to connect to a remote
+@strong{MySQL} running on an NT server.
+
+If @code{mysqld} doesn't start please check whether or not the
+@file{\mysql\mysql.err} file contains any reason for this. You can also
+try to start it with @code{mysqld --standalone}; In this case you may
+get some useful information on the screen that may help solve this.
+
+The last option is to start @code{mysqld} with @code{--debug}. In this
+case @code{mysqld} will write a log file in @file{\mysqld.trace}
+that should contain the reason why @code{mysqld} doesn't start. If you
+make a bug report about this, please only send the lines where something
+seams to go wrong to the mailing list!
+
+@node NT start, Win32 running, Win95 start, Win32
+@subsection Starting MySQL on NT / Win200
+
+The Win95/Win98 section also applies to @strong{MySQL} on NT / Win2000, with
+the following differences:
+
+To get @strong{MySQL} to work with TCP/IP on NT, you must install
+service pack 3 (or newer)!
+
+Note that everything in the following that applies for NT, also applies
+for Win2000!
+
+For NT / Win2000, the server name is @code{mysqld-nt}. Normally you
+should install @strong{MySQL} as a service on NT/Win2000:
+
+@example
+C:\mysql\bin\mysqld-nt --install
+@end example
+
+(You could use the @code{mysqld} or @code{mysqld-opt} servers on NT,
+but those cannot be started as a service or use named pipes.)
+
+You can start and stop the @strong{MySQL} service with:
+
+@example
+NET START mysql
+NET STOP mysql
+@end example
+
+Note that in this case you can't use any other options for @code{mysqld-nt}!
+
+You can also run @code{mysqld-nt} as a standalone program on NT if you need
+to start @code{mysqld-nt} with any options! If you start @code{mysqld-nt}
+without options on NT, @code{mysqld-nt} tries to starts itself as a service
+with the default service options. If you have stopped @code{mysqld-nt}, you
+have to start it with @code{NET START mysql}.
+
+The service is installed with the name @code{MySql}. Once installed, it must
+be started using Services Control Manager (SCM) Utility (found in Control
+Panel) or by using the @code{NET START MySQL} command. If any options are
+desired, they must be specified as "Startup parameters" in the SCM utility
+before you start the @strong{MySQL} service. Once running, @code{mysqld-nt}
+can be stopped using @code{mysqladmin} or from the SCM utility or by using
+the command @code{NET STOP MySQL}. If you use SCM to stop @code{mysqld-nt},
+there is a strange message from SCM about @code{mysqld shutdown normally}.
+When run as a service, @code{mysqld-nt} has no access to a console and so no
+messages can be seen.
+
+On NT you can get the following service error messages:
+
+@multitable @columnfractions .3 .7
+@item Permission Denied @tab Means that it cannot find @code{mysqld-nt.exe}
+@item Cannot Register @tab Means that the path is incorrect
+@end multitable
+
+If you have problems installing @code{mysqld-nt} as a service, try starting
+it with the full path:
+
+@example
+C:\mysql\bin\mysqld-nt --install
+@end example
+
+If this doesn't work, you can get @code{mysqld-nt} to start properly by fixing
+the path in the registry!
+
+If you don't want to start @code{mysqld-nt} as a service, you can start it as
+follows:
+
+@example
+C:\mysql\bin\mysqld-nt --standalone
+@end example
+
+or
+
+@example
+C:\mysql\bin\mysqld --standalone --debug
+@end example
+
+The last version gives you a debug trace in @file{C:\mysqld.trace}.
+
+@node Win32 running, Win32 and SSH, NT start, Win32
+@subsection Running MySQL on Win32
+
+@strong{MySQL} supports TCP/IP on all Win32 platforms and named pipes on NT.
+The default is to use named pipes for local connections on NT and TCP/IP for
+all other cases if the client has TCP/IP installed. The host name specifies
+which protocol is used:
+
+@multitable @columnfractions .3 .7
+@strong{Host name} @tab @strong{protocol}
+@item NULL (none) @tab On NT, try named pipes first; if that doesn't work, use TCP/IP. On Win95/Win98, TCP/IP is used.
+@item . @tab Named pipes
+@item localhost @tab TCP/IP to current host
+@item hostname @tab TCP/IP
+@end multitable
+
+You can force a @strong{MySQL} client to use named pipes by specifying the
+@code{--pipe} option. Use the @code{--socket} option to specify the name of
+the pipe.
+
+You can test whether or not @strong{MySQL} is working by executing the
+following commands:
+
+@example
+C:\mysql\bin\mysqlshow
+C:\mysql\bin\mysqlshow -u root mysql
+C:\mysql\bin\mysqladmin version status proc
+C:\mysql\bin\mysql test
+@end example
+
+If @code{mysqld} is slow to answer to connections on Win95/Win98, there is
+probably a problem with your DNS. In this case, start @code{mysqld} with
+@code{--skip-name-resolve} and use only @code{localhost} and IP numbers in
+the @strong{MySQL} grant tables. You can also avoid DNS when connecting to a
+@code{mysqld-nt} @strong{MySQL} server running on NT by using the
+@code{--pipe} argument to specify use of named pipes. This works for most
+@strong{MySQL} clients.
+
+There are two versions of the @strong{MySQL} command line tool:
+@multitable @columnfractions .15 .85
+@item @code{mysql} @tab Compiled on native Win32, which offers very limited text
+editing capabilities.
+@item @code{mysqlc} @tab Compiled with the Cygnus GNU compiler and libraries, which offers @code{readline} editing.
+@end multitable
+
+If you want to use @code{mysqlc.exe}, you must copy
+@file{C:\mysql\lib\cygwinb19.dll} to @file{\windows\system} (or similar
+place).
+
+The default privileges on Win32 give all local users full privileges
+to all databases. To make @strong{MySQL} more secure, you
+should set a password for all users and remove the row in the
+@code{mysql.user} table that has @code{Host='localhost'} and
+@code{User=''}.
+
+You should also add a password for the @code{root} user:
+(The following example starts by removing the anonymous user, that allows
+anyone to access the 'test' database)
+
+@example
+C:\mysql\bin\mysql mysql
+mysql> DELETE FROM user WHERE Host='localhost' AND User='';
+mysql> QUIT
+C:\mysql\bin\mysqladmin reload
+C:\mysql\bin\mysqladmin -u root password your_password
+@end example
+
+After you've set the password, if you want to take down the @code{mysqld}
+server, you can do so using this command:
+
+@example
+mysqladmin --user=root --password=your_password shutdown
+@end example
+
+If you are using the old shareware version of @strong{MySQL} 3.21 under
+Windows, the above command will fail with an error: @code{parse error
+near 'SET OPTION password'}. This is because the old shareware version,
+which is based on @strong{MySQL} 3.21, doesn't have the @code{SET PASSWORD}
+command. The fix is in this case is to upgrade to the 3.22 shareware
+version.
+
+With the newer @strong{MySQL} versions you can easily add new users
+and change privileges with @code{GRANT} and @code{REVOKE} commands.
+@xref{GRANT}.
+
+@node Win32 and SSH, Win32 symbolic links, Win32 running, Win32
+@subsection Connecting to a remote MySQL from Win32 with SSH
+
+Here is a note about how to connect to get a secure connection to remote MySQL
+server with SSH (by David Carlson).
+
+@itemize @bullet
+@item
+Install SSH client on your windows machine - I used a free SSH client
+from @uref{http://www.doc.ic.ac.uk/~ci2/ssh/}.
+Other useful links:
+@uref{http://www.npaci.edu/Security/npaci_security_software.html} and
+@uref{http://www.npaci.edu/Security/samples/ssh32_windows/index.html}.
+@item
+Start SSH. Set Host Name = yourmysqlserver name or IP address. Set
+userid=your userid to log in to your server
+@item
+Click on "local forwards". Set @code{local port: 3306},
+@code{host: localhost}, @code{remote port: 3306}
+@item
+Save everything, otherwise you'll have to redo it the next time.
+@item
+Log in to your server with SSH.
+@item
+Start some ODBC application (for example Access)
+@item
+Create a new file and link to mySQL using the ODBC driver the same way
+you normally do except for server, user "localhost".
+@end itemize
+
+That's it. It works very well with a direct Internet connection. I'm
+having problems with SSH conflicting with my Win95 network and Wingate -
+but that'll be the topic of a posting on another software company's
+usegroup!
+
+@findex Symbolic links
+@findex Using multiple disks to start data
+@node Win32 symbolic links, Win32 compiling, Win32 and SSH, Win32
+@subsection Splitting data across different disks under Win32
+
+On windows @strong{MySQL} 3.23.16 and above is compiled with the
+@code{-DUSE_SYMDIR} option. This allows you to put a database on
+different disk by adding a symbolic link to it (in a similar manner that
+symbolic links works on Unix).
+
+On windows you make a symbolic link to a database by creating a file
+that contains the path to the destination directory and saving this in
+the @code{mysql_data} directory under the filename @code{database.sym}.
+Note that the symbolic link will only be used if the directory
+@code{mysql_data_dir\database} doesn't exist.
+
+For example if you want to have database @code{foo} on @file{D:\data\foo} you
+should create the file @file{C:\mysql\data\foo.sym} that should contains the
+text @code{D:\data\foo}. After this, all tables created in the database
+@code{foo} will be created in @file{D:\data\foo}.
+
+@node Win32 compiling, Win32 vs Unix, Win32 symbolic links, Win32
+@subsection Compiling MySQL clients on Windows.
+
+In your source files, you should include @file{windows.h} before you include
+@code{mysql.h}:
+
+@example
+#if defined(_WIN32) || defined(_WIN64)
+#include <windows.h>
+#endif
+#include <mysql.h>
+@end example
+
+You can either link your code with the dynamic @file{libmysql.lib} library,
+which is just a wrapper to load in @file{libmysql.dll} on demand, or link
+with the static @file{mysqlclient.lib} library.
+
+Note that as the mysqlclient libraries are compiled as threaded libraries,
+you should also compile your code to be multi-threaded!
+
+@node Win32 vs Unix, , Win32 compiling, Win32
+@subsection MySQL-Win32 compared to Unix MySQL
+
+@strong{MySQL}-Win32 has by now proven itself to be very stable. This version
+of @strong{MySQL} has the same features as the corresponding Unix version
+with the following exceptions:
+
+@table @strong
+@item Win95 and threads
+Win95 leaks about 200 bytes of main memory for each thread creation. Because
+of this, you shouldn't run @code{mysqld} for an extended time on Win95 if
+you do many connections, because each connection in @strong{MySQL} creates
+a new thread! WinNT and Win98 don't suffer from this bug.
+
+@item Concurrent reads
+@strong{MySQL} depends on the @code{pread()} and @code{pwrite()} calls to be
+able to mix @code{INSERT} and @code{SELECT}. As windows doesn't support these
+calls, @strong{MySQL} can't currently handle concurrent reads on windows.
+We plan to fix this by adding an extra mutex to each open file and simulate
+@code{pread()}/@code{pwrite()}.
+
+@item Blocking read
+@strong{MySQL} uses a blocking read for each connection.
+This means that:
+
+@itemize @bullet
+@item
+A connection will not be disconnected automatically after 8 hours, as happens
+with the Unix version of @strong{MySQL}.
+
+@item
+If a connection ``hangs,'' it's impossible to break it without killing
+@strong{MySQL}.
+
+@item
+@code{mysqladmin kill} will not work on a sleeping connection.
+
+@item
+@code{mysqladmin shutdown} can't abort as long as there are sleeping
+connections.
+@end itemize
+
+We plan to fix this in the near future.
+
+@item UDF functions
+For the moment, @strong{MySQL}-Win32 does not support user definable functions.
+
+@item @code{DROP DATABASE}
+You can't drop a database that is in use by some thread.
+
+@item Killing @strong{MySQL} from the task manager
+You can't kill @strong{MySQL} from the task manager or with the shutdown
+utility in Windows95. You must take it down with @code{mysqladmin shutdown}.
+
+@item Case-insensitive names
+Filenames are case insensitive on Win32, so database and table names
+are also case insensitive in @strong{MySQL} for Win32. The only restriction is
+that database and table names must be given in the same case throughout a
+given statement. The following query would not work because it refers to
+a table both as @code{my_table} and as @code{MY_TABLE}:
+@example
+SELECT * FROM my_table WHERE MY_TABLE.col=1;
+@end example
+
+@item The @samp{\} directory character
+Pathname components in Win95 are separated by @samp{\} characters, which is
+also the escape character in @strong{MySQL}. If you are using @code{LOAD
+DATA INFILE} or @code{SELECT ... INTO OUTFILE}, you must double the @samp{\}
+character or use Unix style filenames @samp{/} characters:
+@example
+LOAD DATA INFILE "C:\\tmp\\skr.txt" INTO TABLE skr;
+SELECT * INTO OUTFILE 'C:/tmp/skr.txt' FROM skr;
+@end example
+
+@item @code{Can't open named pipe} error
+If you use the shareware version of @strong{MySQL}-Win32 on NT with the
+newest mysql-clients you will get the following error:
+
+@example
+error 2017: can't open named pipe to host: . pipe...
+@end example
+
+@tindex .my.cnf file
+This is because the release version of @strong{MySQL} uses
+named pipes on NT by default. You can avoid this error by using the
+@code{--host=localhost} option to the new @strong{MySQL} clients
+or create a file @file{C:\my.cnf} that contains the following information:
+
+@example
+[client]
+host = localhost
+@end example
+
+@item @code{Access denied for user} error
+If you get the error @code{Access denied for user: 'some-user@@unknown'
+to database 'mysql'} when accessing a @strong{MySQL} server on the same
+machine, this means that @strong{MySQL} can't resolve your host name
+properly.
+
+To fix this, you should create a file @file{\windows\hosts} with the
+following information:
+
+@example
+127.0.0.1 localhost
+@end example
+@end table
+
+Here are some open issues for anyone who might want to help us with the Win32
+release:
+
+@itemize @bullet
+@item
+Make a single user @code{MYSQL.DLL} server. This should include everything in
+a standard @strong{MySQL} server, except thread creation. This will make
+@strong{MySQL} much easier to use in applications that don't need a true
+client/server and don't need to access the server from other hosts.
+
+@item
+Add some nice ``start'' and ``shutdown'' icons to the @strong{MySQL} installation.
+
+@item
+Create a tool to manage registry entries for the @strong{MySQL} startup
+options. The registry entry reading is already coded into @code{mysqld.cc},
+but it should be recoded to be more ``parameter'' oriented.
+The tool should also be able to update the @file{\my.cnf} file if the user
+would prefer to use this instead of the registry.
+
+@item
+When registering @code{mysqld} as a service with @code{--install} (on NT)
+it would be nice if you could also add default options on the command line.
+For the moment, the workaround is to update the @file{C:\my.cnf} file
+instead.
+
+@item
+When you suspend a laptop running Win95, the @code{mysqld}
+daemon doesn't accept new connections when the laptop is resumed.
+We don't know if this is a problem with Win95, TCP/IP or @strong{MySQL}.
+
+@item
+It would be real nice to be able to kill @code{mysqld} from the
+task manager. For the moment, you must use @code{mysqladmin shutdown}.
+
+@item
+Port @code{readline} to Win32 for use in the @code{mysql} command line tool.
+
+@item
+GUI versions of the standard @strong{MySQL} clients (@code{mysql},
+@code{mysqlshow}, @code{mysqladmin}, and @code{mysqldump}) would be nice.
+
+@item
+It would be nice if the socket ``read'' and ``write'' functions in
+@file{net.c} were interruptible. This would make it possible to kill open
+threads with @code{mysqladmin kill} on Win32.
+
+@item
+Documentation of which Windows programs work with
+@strong{MySQL}-Win32/@strong{MyODBC} and what must be done to get them working.
+
+@item
+@code{mysqld} always starts in the "C" locale and not in the default locale.
+We would like to have @code{mysqld} use the current locale for the sort order.
+
+@item
+Port @code{sqlclient} to Win32 (almost done) and add more features to it!
+
+@item
+Add more options to MysqlManager.
+
+@item
+Change the communication protocol between the server and client to use Windows
+internal communication instead of sockets and TCP/IP.
+
+@item
+Implement UDF functions with @code{.DLL}s.
+
+@item
+Add macros to use the faster thread-safe increment/decrement methods
+provided by Win32.
+
+@end itemize
+
+Other Win32-specific issues are described in the @file{README} file that comes
+with the @strong{MySQL}-Win32 distribution.
+
+@node OS/2, MySQL binaries, Win32, Installing
+@section OS/2 notes
+
+@strong{MySQL} uses quite a few open files. Because of this, you
+should add something like the following to your @file{CONFIG.SYS} file:
+
+@example
+SET EMXOPT=-c -n -h1024
+@end example
+
+If you don't do this, you will probably run into the following error:
+
+@example
+File 'xxxx' not found (Errcode: 24)
+@end example
+
+When using @strong{MySQL} with OS/2 Warp 3, FixPack 29 or above is
+required. With OS/2 Warp 4, FixPack 4 or above is required. This is a
+requirement of the Pthreads library. @strong{MySQL} must be installed
+in a partition that supports long file names such as HPFS, FAT32, etc.
+
+The @file{INSTALL.CMD} script must be run from OS/2's own @file{CMD.EXE}
+and may not work with replacement shells such as @file{4OS2.EXE}.
+
+The @file{scripts/mysql-install-db} script has been renamed: it is now called
+@file{install.cmd} and is a REXX script which will set up the default
+@strong{MySQL} security settings and create the WorkPlace Shell icons
+for @strong{MySQL}.
+
+Dynamic module support is compiled in but not fully tested. Dynamic
+modules should be compiled using the Pthreads runtime library.
+
+@example
+gcc -Zdll -Zmt -Zcrtdll=pthrdrtl -I../include -I../regex -I.. \
+ -o example udf_example.cc -L../lib -lmysqlclient udf_example.def
+mv example.dll example.udf
+@end example
+
+@strong{Note:} Due to limitations in OS/2, UDF module name stems must not
+exceed 8 characters. Modules are stored in the @file{/mysql2/udf}
+directory; the @code{safe-mysqld.cmd} script will put this directory in
+the @code{BEGINLIBPATH} environment variable. When using UDF modules,
+specified extensions are ignored --- it is assumed to be @file{.udf}.
+For example, in Unix, the shared module might be named @file{example.so}
+and you would load a function from it like this:
+
+@example
+CREATE FUNCTION metaphon RETURNS STRING SONAME "example.so";
+@end example
+
+Is OS/2, the module would be named @file{example.udf}, but you would not
+specify the module extension:
+
+@example
+CREATE FUNCTION metaphon RETURNS STRING SONAME "example";
+@end example
+
+@node MySQL binaries, Post-installation, OS/2, Installing
+@section MySQL binaries
+
+As a service, we at MySQL AB provides a set of binary distributions of
+@strong{MySQL} that are compiled at our site or at sites where customers
+kindly have given us access to their machines.
+
+These distributions are generated with
+@code{scripts/make_binary_distribution} and are configured with the
+following compilers and options:
+
+@table @asis
+@item SunOS 4.1.4 2 sun4c with @code{gcc} 2.7.2.1
+@code{CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --disable-shared --with-extra-charsets=complex}
+
+@item SunOS 5.5.1 sun4u with @code{egcs} 1.0.3a
+@code{CC=gcc CFLAGS="-O6 -fomit-frame-pointer" CXX=gcc CXXFLAGS="-O6 -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-low-memory --with-extra-charsets=complex}
+
+@item SunOS 5.6 sun4u with @code{egcs} 2.90.27
+@code{CC=gcc CFLAGS="-O6 -fomit-frame-pointer" CXX=gcc CXXFLAGS="-O6 -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-low-memory --with-extra-charsets=complex}
+
+@item SunOS 5.6 i86pc with @code{gcc} 2.8.1
+@code{CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-low-memory --with-extra-charsets=complex}
+
+@item Linux 2.0.33 i386 with @code{pgcc} 2.90.29 (@code{egcs} 1.0.3a)
+@code{CFLAGS="-O6 -mpentium -mstack-align-double -fomit-frame-pointer" CXX=gcc CXXFLAGS="-O6 -mpentium -mstack-align-double -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --enable-assembler --with-mysqld-ldflags=-all-static --with-extra-charsets=complex}
+
+@item Linux 2.2.x with x686 with @code{gcc} 2.95.2
+@code{CFLAGS="-O6 -mpentiumpro -fomit-frame-pointer" CXX=gcc CXXFLAGS="-O6 -mpentiumpro -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --enable-assembler --with-mysqld-ldflags=-all-static --disable-shared --with-extra-charset=complex}
+
+@item SCO 3.2v5.0.4 i386 with @code{gcc} 2.7-95q4
+@code{CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex}
+
+@item AIX 2 4 with @code{gcc} 2.7.2.2
+@code{CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex}
+
+@item OSF1 V4.0 564 alpha with @code{gcc} 2.8.1
+@code{CC=gcc CFLAGS=-O CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-low-memory --with-extra-charsets=complex}
+
+@item Irix 6.3 IP32 with @code{gcc} 2.8.0
+@code{CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex}
+
+@item BSDI BSD/OS 3.1 i386 with @code{gcc} 2.7.2.1
+@code{CC=gcc CXX=gcc CXXFLAGS=-O ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex}
+
+@item BSDI BSD/OS 2.1 i386 with @code{gcc} 2.7.2
+@code{CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex}
+@end table
+
+Anyone who has more optimal options for any of the configurations listed
+above can always mail them to the developer's mailing list at
+@email{developer@@lists.mysql.com}.
+
+RPM distributions prior to @strong{MySQL} 3.22 are user-contributed.
+Beginning with 3.22, some RPMs are generated by us at MySQL AB.
+
+If you want to compile a debug version of @strong{MySQL}, you should add
+@code{--with-debug} or @code{--with-debug=full} to the above configure lines
+and remove any @code{-fomit-frame-pointer} options.
+
+@node Post-installation, Upgrade, MySQL binaries, Installing
+@section Post-installation setup and testing
+
+@menu
+* mysql_install_db:: Problems running @code{mysql_install_db}
+* Starting server:: Problems starting the @strong{MySQL} server
+* Automatic start:: Starting and stopping @strong{MySQL} automatically
+* Command-line options:: Command-line options
+* Option files:: Option files
+@end menu
+
+Once you've installed @strong{MySQL} (from either a binary or source
+distribution), you need to initialize the grant tables, start the server
+and make sure that the server works okay. You may also wish to arrange
+for the server to be started and stopped automatically when your system
+starts up and shuts down.
+
+Normally you install the grant tables and start the server like this
+for installation from a source distribution:
+
+@example
+shell> ./scripts/mysql_install_db
+shell> cd mysql_installation_directory
+* Command-line options:: Command-line options
+shell> ./bin/safe_mysqld &
+@end example
+
+For a binary distribution, do this:
+
+@example
+shell> cd mysql_installation_directory
+shell> ./bin/mysql_install_db
+shell> ./bin/safe_mysqld &
+@end example
+
+Testing is most easily done from the top-level directory of the @strong{MySQL}
+distribution. For a binary distribution, this is your installation directory
+(typically something like @file{/usr/local/mysql}). For a source
+distribution, this is the main directory of your @strong{MySQL} source tree.
+
+In the commands shown below in this section and in the following
+subsections, @code{BINDIR} is the path to the location in which programs
+like @code{mysqladmin} and @code{safe_mysqld} are installed. For a
+binary distribution, this is the @file{bin} directory within the
+distribution. For a source distribution, @code{BINDIR} is probably
+@file{/usr/local/bin}, unless you specified an installation directory
+other than @file{/usr/local} when you ran @code{configure}.
+@code{EXECDIR} is the location in which the @code{mysqld} server is
+installed. For a binary distribution, this is the same as
+@code{BINDIR}. For a source distribution, @code{EXECDIR} is probably
+@file{/usr/local/libexec}.
+
+Testing is described in detail below:
+
+@enumerate
+@item
+If necessary, start the @code{mysqld} server and set up the initial
+@strong{MySQL} grant tables containing the privileges that determine how
+users are allowed to connect to the server. This is normally done with the
+@code{mysql_install_db} script:
+
+@example
+shell> scripts/mysql_install_db
+@end example
+
+Typically, @code{mysql_install_db} needs to be run only the first time you
+install @strong{MySQL}. Therefore, if you are upgrading an existing
+installation, you can skip this step. (However, @code{mysql_install_db} is
+quite safe to use and will not update any tables that already exist, so if
+you are unsure what to do, you can always run @code{mysql_install_db}.)
+
+@code{mysql_install_db} creates six tables (@code{user}, @code{db},
+@code{host}, @code{tables_priv}, @code{columns_priv} and @code{func}) in the
+@code{mysql} database. A description of the initial privileges is given in
+@ref{Default privileges}. Briefly, these privileges allow the @strong{MySQL}
+@code{root} user to do anything, and allow anybody to create or use databases
+with a name of @code{'test'} or starting with @code{'test_'}.
+
+If you don't set up the grant tables, the following error will appear in the
+log file when you start the server:
+
+@tindex host.frm, problems finding
+@example
+mysqld: Can't find file: 'host.frm'
+@end example
+
+The above may also happens with a binary @strong{MySQL} distribution if you
+don't start @strong{MySQL} by executing exactly @code{./bin/safe_mysqld}!
+
+You might need to run @code{mysql_install_db} as @code{root}. However,
+if you prefer, you can run the @strong{MySQL} server as an unprivileged
+(non-@code{root}) user, provided that user can read and write files in
+the database directory. Instructions for running @strong{MySQL} as an
+unprivileged user are given in @ref{Changing MySQL user, , Changing
+@strong{MySQL} user}.
+
+If you have problems with @code{mysql_install_db}, see
+@ref{mysql_install_db, , @code{mysql_install_db}}.
+
+There are some alternatives to running the @code{mysql_install_db}
+script as it is provided in the @strong{MySQL} distribution:
+
+@itemize @bullet
+@item
+You may want to edit @code{mysql_install_db} before running it, to
+change the initial privileges that are installed into the grant tables.
+This is useful if you want to install @strong{MySQL} on a lot of machines
+with the same privileges. In this case you probably should need only to add
+a few extra @code{INSERT} statements to the @code{mysql.user} and
+@code{mysql.db} tables!
+
+@item
+If you want to change things in the grant tables after installing them, you
+can run @code{mysql_install_db}, then use @code{mysql -u root mysql} to
+connect to the grant tables as the @strong{MySQL} @code{root} user and issue
+SQL statements to modify the grant tables directly.
+
+@item
+It is possible to recreate the grant tables completely after they have
+already been created. You might want to do this if you've already installed
+the tables but then want to recreate them after editing
+@code{mysql_install_db}.
+@end itemize
+
+For more information about these alternatives, see @ref{Default privileges}.
+
+@item
+Start the @strong{MySQL} server like this:
+@example
+shell> cd mysql_installation_directory
+shell> bin/safe_mysqld &
+@end example
+If you have problems starting the server, see @ref{Starting server}.
+
+@item
+Use @code{mysqladmin} to verify that the server is running. The following
+commands provide a simple test to check that the server is up and responding
+to connections:
+
+@example
+shell> BINDIR/mysqladmin version
+shell> BINDIR/mysqladmin variables
+@end example
+
+The output from @code{mysqladmin version} varies slightly depending on your
+platform and version of @strong{MySQL}, but should be similar to that shown
+below:
+
+@example
+shell> BINDIR/mysqladmin version
+mysqladmin Ver 6.3 Distrib 3.22.9-beta, for pc-linux-gnu on i686
+TCX Datakonsult AB, by Monty
+
+Server version 3.22.9-beta
+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
+@end example
+
+To get a feeling for what else you can do with @code{BINDIR/mysqladmin},
+invoke it with the @code{--help} option.
+
+@item
+Verify that you can shut down the server:
+
+@example
+shell> BINDIR/mysqladmin -u root shutdown
+@end example
+
+@item
+Verify that you can restart the server. Do this using @code{safe_mysqld} or
+by invoking @code{mysqld} directly. For example:
+
+@example
+shell> BINDIR/safe_mysqld --log &
+@end example
+
+If @code{safe_mysqld} fails, try running it from the @strong{MySQL}
+installation directory (if you are not already there). If that doesn't work,
+see @ref{Starting server}.
+
+@item
+Run some simple tests to verify that the server is working.
+The output should be similar to what is shown below:
+
+@example
+shell> BINDIR/mysqlshow
++-----------+
+| Databases |
++-----------+
+| mysql |
++-----------+
+
+shell> BINDIR/mysqlshow mysql
+Database: mysql
++--------------+
+| Tables |
++--------------+
+| columns_priv |
+| db |
+| func |
+| host |
+| tables_priv |
+| user |
++--------------+
+
+shell> BINDIR/mysql -e "select host,db,user from db" mysql
++------+--------+------+
+| host | db | user |
++------+--------+------+
+| % | test | |
+| % | test_% | |
++------+--------+------+
+@end example
+
+There is also a benchmark suite in the @file{sql-bench} directory (under the
+@strong{MySQL} installation directory) that you can use to compare how
+@strong{MySQL} performs on different platforms. The @file{sql-bench/Results}
+directory contains the results from many runs against different databases and
+platforms. To run all tests, execute these commands:
+
+@example
+shell> cd sql-bench
+shell> run-all-tests
+@end example
+
+If you don't have the @file{sql-bench} directory, you are probably using an
+RPM for a binary distribution. (Source distribution RPMs include the
+benchmark directory.) In this case, you must first install the benchmark
+suite before you can use it. Beginning with @strong{MySQL} 3.22, there are
+benchmark RPM files named @file{mysql-bench-VERSION-i386.rpm} that contain
+benchmark code and data.
+
+If you have a source distribution, you can also run the tests in the
+@file{tests} subdirectory. For example, to run @file{auto_increment.tst}, do
+this:
+
+@example
+shell> BINDIR/mysql -vvf test < ./tests/auto_increment.tst
+@end example
+
+The expected results are shown in the @file{./tests/auto_increment.res} file.
+@end enumerate
+
+@node mysql_install_db, Starting server, Post-installation, Post-installation
+@subsection Problems running @code{mysql_install_db}
+
+This section lists problems you might encounter when you run
+@code{mysql_install_db}:
+
+@table @strong
+@item @code{mysql_install_db} doesn't install the grant tables
+
+You may find that @code{mysql_install_db} fails to install the grant
+tables and terminates after displaying the following messages:
+
+@example
+starting mysqld daemon with databases from XXXXXX
+mysql daemon ended
+@end example
+
+In this case, you should examine the log file very carefully! The log
+should be located in the directory @file{XXXXXX} named by the error message,
+and should indicate why @code{mysqld} didn't start. If you don't understand
+what happened, include the log when you post a bug report using
+@code{mysqlbug}!
+@xref{Bug reports}.
+
+@item There is already a @code{mysqld} daemon running
+
+In this case, you have probably don't have to run @code{mysql_install_db} at
+all. You have to run @code{mysql_install_db} only once, when you install
+@strong{MySQL} the first time.
+
+@item Installing a second @code{mysqld} daemon doesn't work when one daemon is running
+
+This can happen when you already have an existing @strong{MySQL}
+installation, but want to put a new installation in a different place (e.g.,
+for testing, or perhaps you simply want to run two installations at the same
+time). Generally the problem that occurs when you try to run the second
+server is that it tries to use the same socket and port as the old one. In
+this case you will get the error message: @code{Can't start server: Bind on
+TCP/IP port: Address already in use} or @code{Can't start server : Bind on
+unix socket...} You can start the new server with a different socket and
+port as follows:
+
+@tindex MYSQL_UNIX_PORT environment variable
+@tindex MYSQL_TCP_PORT environment variable
+@tindex Environment variable, MYSQL_UNIX_PORT
+@tindex Environment variable, MYSQL_TCP_PORT
+@example
+shell> MYSQL_UNIX_PORT=/tmp/mysqld-new.sock
+shell> MYSQL_TCP_PORT=3307
+shell> export MYSQL_UNIX_PORT MYSQL_TCP_PORT
+shell> scripts/mysql_install_db
+shell> bin/safe_mysqld &
+@end example
+
+The environment variables appendix includes a list of other environment
+variables you can use to affect @code{mysqld}. @xref{Environment variables}.
+
+After this, you should edit your server boot script to start both daemons
+with different sockets and ports. For example, it could invoke
+@code{safe_mysqld} twice, but with different @code{--socket}, @code{--port}
+and @code{--basedir} options for each invocation.
+
+@item You don't have write access to @file{/tmp}
+
+If you don't have write access to create a socket file at the default place
+(in @file{/tmp}) or permission to create temporary files in @file{/tmp,}
+you will get an error when running @code{mysql_install_db} or when
+starting or using @code{mysqld}.
+
+You can specify a different socket and temporary directory as follows:
+
+@tindex TMPDIR environment variable
+@tindex MYSQL_UNIX_PORT environment variable
+@tindex Environment variable, TMPDIR
+@tindex Environment variable, MYSQL_UNIX_PORT
+@example
+shell> TMPDIR=/some_tmp_dir/
+shell> MYSQL_UNIX_PORT=/some_tmp_dir/mysqld.sock
+shell> export TMPDIR MYSQL_UNIX_PORT
+@end example
+
+@file{some_tmp_dir} should be the path to some directory for which you
+have write permission. @xref{Environment variables}.
+
+
+After this you should be able to run @code{mysql_install_db} and start
+the server with these commands:
+
+@example
+shell> scripts/mysql_install_db
+shell> BINDIR/safe_mysqld &
+@end example
+
+@item @code{mysqld} crashes immediately
+
+If you are running RedHat 5.0 with a version of @code{glibc} older than
+2.0.7-5, you should make sure you have installed all @code{glibc} patches!
+There is a lot of information about this in the @strong{MySQL} mail
+archives. Links to the mail archives are available at the online
+@uref{http://www.mysql.com/documentation/, @strong{MySQL} documentation page}.
+Also, see @ref{Linux}.
+
+You can also start @code{mysqld} manually using the @code{--skip-grant-tables}
+option and add the privilege information yourself using @code{mysql}:
+
+@example
+shell> BINDIR/safe_mysqld --skip-grant-tables &
+shell> BINDIR/mysql -u root mysql
+@end example
+
+From @code{mysql}, manually execute the SQL commands in
+@code{mysql_install_db}. Make sure you run @code{mysqladmin
+flush-privileges} or @code{mysqladmin reload} afterward to tell the server to
+reload the grant tables.
+@end table
+
+@node Starting server, Automatic start, mysql_install_db, Post-installation
+@subsection Problems starting the MySQL server
+
+Generally, you start the @code{mysqld} server in one of three ways:
+
+@itemize @bullet
+@item
+By invoking @code{mysql.server}. This script is used primarily at
+system startup and shutdown, and is described more fully in
+@ref{Automatic start}.
+@item
+By invoking @code{safe_mysqld}, which tries to determine the proper options
+for @code{mysqld} and then runs it with those options.
+@item
+On NT you should install @code{mysqld} as a service as follows:
+@example
+bin\mysqld-nt --install # Install MySQL as a service
+@end example
+
+You can now start/stop @code{mysqld} as follows:
+@example
+NET START mysql
+NET STOP mysql
+@end example
+
+Note that in this case you can't use any other options for @code{mysqld}!
+
+You can remove the service as follows:
+@example
+bin\mysqld-nt --remove # remove MySQL as a service
+@end example
+@item
+By invoking @code{mysqld} directly.
+@end itemize
+
+Whichever method you use to start the server, if it fails to start up
+correctly, check the log file to see if you can find out why. Log files
+are located in the data directory (typically
+@file{/usr/local/mysql/data} for a binary distribution,
+@file{/usr/local/var} for a source distribution),
+@file{\mysql\mysql.err} on Windows. Look in the data directory for
+files with names of the form @file{host_name.err} and
+@file{host_name.log} where @code{host_name} is the name of your server
+host. Then check the last few lines of these files:
+
+@example
+shell> tail host_name.err
+shell> tail host_name.log
+@end example
+
+If you find in the log file something like: the following:
+@example
+000729 14:50:10 bdb: Recovery function for LSN 1 27595 failed
+000729 14:50:10 bdb: warning: ./test/t1.db: No such file or directory
+000729 14:50:10 Can't init databases
+@end example
+
+This means that you started mysqld with @code{--bdb-recover} and that
+Berkeley DB found something wrong with it's log files when it tried to
+recover your databases. To be able to continue, you should move away
+the old Berkeley DB log file from the database directory to some other
+place, where you can later examine these. The log files are named
+@file{log.0000000001}, where the number will increase over time.
+
+When the @code{mysqld} daemon starts up, it changes directory to the
+data directory. This is where it expects to write log files and the pid
+(process ID) file, and where it expects to find databases.
+
+The data directory location is hardwired in when the distribution is
+compiled. However, if @code{mysqld} expects to find the data directory
+somewhere other than where it really is on your system, it will not work
+properly. If you have problems with incorrect paths, you can find out
+what options @code{mysqld} allows and what the default path settings are by
+invoking @code{mysqld} with the @code{--help} option. You can override the
+defaults by specifying the correct pathnames as command-line arguments to
+@code{mysqld}. (These options can be used with @code{safe_mysqld} as well.)
+
+Normally you should need to tell @code{mysqld} only the base directory under
+which @strong{MySQL} is installed. You can do this with the @code{--basedir}
+option. You can also use @code{--help} to check the effect of changing path
+options (note that @code{--help} @emph{must} be the final option of the
+@code{mysqld} command). For example:
+
+@example
+shell> EXECDIR/mysqld --basedir=/usr/local --help
+@end example
+
+Once you determine the path settings you want, start the server without
+the @code{--help} option.
+
+If you get the following error, it means that some other program (or another
+@code{mysqld} server) is already using the TCP/IP port or socket
+@code{mysqld} is trying to use:
+
+@example
+Can't start server: Bind on TCP/IP port: Address already in use
+ or
+Can't start server : Bind on unix socket...
+@end example
+
+Use @code{ps} to make sure that you don't have another @code{mysqld} server
+running. If you can't find another server running, you can try to execute
+the command @code{telnet your-host-name tcp-ip-port-number} and press
+@code{RETURN} a couple of times. If you don't get an error message like
+@code{telnet: Unable to connect to remote host: Connection refused},
+something is using the TCP/IP port @code{mysqld} is trying to use.
+@xref{mysql_install_db, , @code{mysql_install_db}}, and @ref{Multiple
+servers}.
+
+The @code{safe_mysqld} script is written so that it normally is able to start
+a server that was installed from either a source or a binary version of
+@strong{MySQL}, even if these install the server in slightly different
+locations. @code{safe_mysqld} expects one of these conditions to be true:
+
+@itemize @bullet
+@item
+The server and databases can be found relative to the directory from which
+@code{safe_mysqld} is invoked. @code{safe_mysqld} looks under its working
+directory for @file{bin} and @file{data} directories (for binary
+distributions) or for @file{libexec} and @file{var} directories (for source
+distributions). This condition should be met if you execute
+@code{safe_mysqld} from your @strong{MySQL} installation directory (for
+example, @file{/usr/local/mysql} for a binary distribution).
+
+@item
+If the server and databases cannot be found relative to its working directory,
+@code{safe_mysqld} attempts to locate them by absolute pathnames. Typical
+locations are @file{/usr/local/libexec} and @file{/usr/local/var}.
+The actual locations are determined when the distribution was built from which
+@code{safe_mysqld} comes. They should be correct if
+@strong{MySQL} was installed in a standard location.
+@end itemize
+
+Because @code{safe_mysqld} will try to find the server and databases relative
+to its own working directory, you can install a binary distribution of
+@strong{MySQL} anywhere, as long as you start @code{safe_mysqld} from the
+@strong{MySQL} installation directory:
+
+@example
+shell> cd mysql_installation_directory
+shell> bin/safe_mysqld &
+@end example
+
+If @code{safe_mysqld} fails, even when invoked from the @strong{MySQL}
+installation directory, you can modify it to use the path to @code{mysqld}
+and the pathname options that are correct for your system. Note that if you
+upgrade @strong{MySQL} in the future, your modified version of
+@code{safe_mysqld} will be overwritten, so you should make a copy of your
+edited version that you can reinstall.
+
+If @code{mysqld} is currently running, you can find out what path settings
+it is using by executing this command:
+
+@example
+shell> mysqladmin variables
+
+or
+
+shell> mysqladmin -h 'your-host-name' variables
+@end example
+
+If @code{safe_mysqld} starts the server but you can't connect to it,
+you should make sure you have an entry in @file{/etc/hosts} that looks like
+this:
+
+@example
+127.0.0.1 localhost
+@end example
+
+This problem occurs only on systems that don't have a working thread
+library and for which @strong{MySQL} must be configured to use MIT-pthreads.
+
+On Windows, you can try to start @code{mysqld} as follows:
+
+@example
+C:\mysql\bin\mysqld --standalone --debug
+@end example
+
+This will not run in the background and it should also write a trace in
+@file{\mysqld.trace}, which may help you determine the source of your
+problems. @xref{Win32}.
+
+@node Automatic start, Command-line options, Starting server, Post-installation
+@subsection Starting and stopping MySQL automatically
+
+The @code{mysql.server} script can be used to start or stop the server,
+by invoking it with @code{start} or @code{stop} arguments:
+
+@example
+shell> mysql.server start
+shell> mysql.server stop
+@end example
+
+@code{mysql.server} can be found in the @file{share/mysql} directory
+under the @strong{MySQL} installation directory, or in the @file{support-files}
+directory of the @strong{MySQL} source tree.
+
+Before @code{mysql.server} starts the server, it changes directory to
+the @strong{MySQL} installation directory, then invokes
+@code{safe_mysqld}. You might need to edit @code{mysql.server} if you
+have a binary distribution that you've installed in a non-standard
+location. Modify it to @code{cd} into the proper directory before it
+runs @code{safe_mysqld}. If you want the server to run as some specific
+user, you can change the @code{mysql_daemon_user=root} line to use
+another user. You can also modify @code{mysql.server} to pass other
+options to @code{safe_mysqld}.
+
+@code{mysql.server stop} brings down server by sending a signal to it.
+You can take down the server manually by executing @code{mysqladmin shutdown}.
+
+You might want to add these start and stop commands to the appropriate places
+in your @file{/etc/rc*} files when you start using @strong{MySQL} for
+production applications. Note that if you modify @code{mysql.server}, then
+if you upgrade @strong{MySQL} sometime, your modified version will be
+overwritten, so you should make a copy of your edited version that you can
+reinstall.
+
+If your system uses @file{/etc/rc.local} to start external scripts, you
+should append the following to it:
+@example
+/bin/sh -c 'cd /usr/local/mysql ; ./bin/safe_mysqld &'
+@end example
+
+You can also add options for @code{mysql.server} in a global
+@file{/etc/my.cnf} file. A typical @file{/etc/my.cnf} file might look like
+this:
+
+@example
+[mysqld]
+datadir=/usr/local/mysql/var
+socket=/tmp/mysqld.sock
+port=3306
+
+[mysql.server]
+user=mysql
+basedir=/usr/local/mysql
+@end example
+
+The @code{mysql.server} script uses the following variables:
+@code{user}, @code{datadir}, @code{basedir}, @code{bindir} and @code{pid-file}.
+
+@xref{Option files}.
+
+@cindex Command-line options
+@node Command-line options, Option files, Automatic start, Post-installation
+@subsection Command-line options
+
+@code{mysqld} accepts the following command-line options:
+
+@table @code
+
+@item --ansi
+Use ANSI SQL syntax instead of MySQL syntax. @xref{Ansi mode}.
+
+@item -b, --basedir=path
+Path to installation directory. All paths are
+usually resolved relative to this.
+
+@item --big-tables
+Allow big result sets by saving all temporary sets on file. It solves
+most 'table full' errors, but also slows down the queries where
+in-memory tables would suffice. Since version 3.23.2 @strong{MySQL} is
+able to solve it automaticaly by using memory for small temporary
+tables and switching to disk tables where necessary.
+
+@item --bind-address=IP
+IP address to bind to.
+
+@item --character-sets-dir=path
+Directory where character sets are. @xref{Character sets}.
+
+@item --chroot=path
+Chroot mysqld daemon during startup.
+Recommended security measure. It will somewhat limit @code{LOAD DATA INFILE}
+and @code{SELECT ... INTO OUTFILE} though.
+
+@item -h, --datadir=path
+Path to the database root.
+
+@item --default-character-set=charset
+Set the default character set. @xref{Character sets}.
+
+@item --default-table-type=type
+Set the default table type for tables. @xref{Table types}.
+
+@item --delay-key-write-for-all-tables
+Don't flush key buffers between writes for any @code{MyISAM} table.
+@xref{Server parameters}.
+
+@item --enable-locking
+Enable system locking.
+
+@item -T, --exit-info
+Print some debug info at exit.
+
+@item --flush
+Flush all changes to disk after each SQL commands; Normally @strong{MySQL}
+only does a write of all changes to disk after each SQL command, and lets
+the operating system handle the syncing to disk.
+@xref{Crashing}.
+
+@item -?, --help
+Display short help and exit.
+
+@item --init-file=file
+Read SQL commands from this file at startup.
+
+@item -L, --language=...
+Client error messages in given language. May be given as a full path.
+@xref{Languages}.
+
+@item -l, --log[=file]
+Log connections and queries to file
+
+@item --log-update[=file]
+Log updates to @code{file.#} where @code{#} is a unique number if not given.
+@xref{Update log}.
+
+@item --log-isam[=file]
+Log all isam changes to file.
+
+@item --log-long-format
+Log some extra information to update log.
+
+@item --low-priority-updates
+Table-modifying operations (@code{INSERT}/@code{DELETE}/@code{UPDATE})
+will have lower priority than selects.
+It can also be done via @code{@{INSERT | REPLACE | UPDATE | DELETE@}
+LOW_PRIORITY ...} to lower the priority of only one query, or by
+@code{SET OPTION SQL_LOW_PRIORITY_UPDATES=1} to change the
+priority in one thread.
+@xref{Table locking}.
+
+@item --pid-file=path
+Path to pid file used by @code{safe_mysqld}.
+
+@item -P, --port=...
+Port number to listen for TCP/IP connections.
+
+@item -o, --old-protocol
+Use the 3.20 protocol for compatibility with some very old clients.
+@xref{Upgrading-from-3.20}.
+
+@item --one-thread
+Only use one thread (for debugging under Linux). @xref{Debugging server}.
+
+@item -O, --set-variable var=option
+Give a variable an value. @code{--help} lists variables.
+You can find a full description for all variables in the @code{SHOW VARIABLES}
+section in this manual. @xref{SHOW VARIABLES}.
+The tuning server parameters section includes information of how to optimize
+these. @xref{Server parameters}.
+
+@item -Sg, --skip-grant-tables
+This option causes the server not to use the privilege system at all. This
+gives everyone @emph{full access} to all databases! (You can tell a running
+server to start using the grant tables again by executing @code{mysqladmin
+flush-privileges} or @code{mysqladmin reload}.)
+
+@item --safe-mode
+Skip some optimize stages.
+Implies @code{--skip-delay-key-write}.
+
+@item --secure
+IP numbers returned by the @code{gethostbyname()} system call are
+checked to make sure they resolve back to the original hostname. This
+makes it harder for someone on the outside to get access by pretending
+to be another host. This option also adds some sanity checks of
+hostnames. The option is turned off by default in @strong{MySQL} 3.21
+because sometimes it takes a long time to perform backward resolutions.
+@strong{MySQL} 3.22 caches hostnames (unless @code{--skip-host-cache} is
+used) and has this option enabled by default.
+
+@item --skip-delay-key-write
+Ignore the @code{delay_key_write} option for all tables.
+@xref{Server parameters}.
+
+@item --skip-locking
+Don't use system locking. To use @code{isamchk} or @code{myisamchk} one has
+to shut down the server. @xref{Stability}. Note that in @strong{MySQL} 3.23
+one can use @code{REPAIR} and @code{CHECK} to repair/check @code{MyISAM}
+tables.
+
+@item --skip-name-resolve
+Hostnames are not resolved. All @code{Host} column values in the grant
+tables must be IP numbers or @code{localhost}.
+
+@item --skip-networking
+Don't listen for TCP/IP connections at all.
+All interaction with @code{mysqld} must be made via Unix sockets.
+This option is highly recommended for systems where only local requests
+are allowed. However, this option is unsuitable for systems that use
+MIT-pthreads, because the MIT-pthreads package doesn't support Unix
+sockets.
+
+@item --skip-new
+Don't use new, possible wrong routines.
+Implies @code{--skip-delay-key-write}.
+This will also set default table type to @code{ISAM}. @xref{ISAM}.
+
+@item --skip-host-cache
+Never use host name cache for faster name-ip resolution, but query
+DNS server on every connect instead.
+
+@item --skip-show-database
+Don't allow 'SHOW DATABASE' commands, unless the user has
+@strong{process} privilege.
+
+@item --skip-thread-priority
+Disable using thread priorities for faster responce time.
+
+@item --socket=path
+Socket file to use for local connections instead of default
+@code{/tmp/mysql.sock}.
+
+@item -t, --tmpdir=path
+Path for temporary files. It may be useful if your default @code{/tmp}
+directory resides on a partition too small to hold temporary tables.
+
+@item -u, --user=user_name
+Run @code{mysqld} daemon as user @code{user_name}. This option is
+@emph{mandatory} when starting @code{mysqld} as root.
+
+@item -V, --version
+output version information and exit
+
+@end table
+
+@cindex Default options
+@cindex Option files
+@node Option files, , Command-line options, Post-installation
+@subsection Option files
+
+@strong{MySQL} 3.22 can read default startup options for the server and
+for clients from option files.
+
+@strong{MySQL} reads default options from the following files on Unix:
+
+@tindex .my.cnf file
+@multitable @columnfractions .3 .7
+@item @strong{Filename} @tab @strong{Purpose}
+@item @code{/etc/my.cnf} @tab Global options
+@item @code{DATADIR/my.cnf} @tab Server-specific options
+@item @code{~/.my.cnf} @tab User-specific options
+@end multitable
+
+@code{DATADIR} is the @strong{MySQL} data directory (typically
+@file{/usr/local/mysql/data} for a binary installation, or
+@file{/usr/local/var} for a source installation). Note that this is the
+directory that was specified at configuration time, not the one specified
+with @code{--datadir} when @code{mysqld} starts up! (@code{--datadir} has no
+effect on where the server looks for option files, because it looks for them
+before it processes any command-line arguments.)
+
+@strong{MySQL} reads default options from the following files on Win32:
+
+@multitable @columnfractions .3 .7
+@item @strong{Filename} @tab @strong{Purpose}
+@item @code{windows-system-directory\my.ini}
+@item @code{C:\my.cnf} @tab Global options
+@item @code{C:\mysql\data\my.cnf} @tab Server-specific options
+@end multitable
+
+Note that you on Win32 should specify all paths with @code{/} instead of
+@code{\}. If you use @code{\}, you need to specify this twice, as
+@code{\} is the escape character in @strong{MySQL}.
+
+@cindex Environment variables
+@strong{MySQL} tries to read option files in the order listed above. If
+multiple option files exist, an option specified in a file read later takes
+precedence over the same option specified in a file read earlier. Options
+specified on the command line take precedence over options specified in any
+option file. Some options can be specified using environment variables.
+Options specified on the command line or in option files take precedence over
+environment variable values. @xref{Environment variables}.
+
+The following programs support option files: @code{mysql},
+@code{mysqladmin}, @code{mysqld}, @code{mysqldump}, @code{mysqlimport},
+@code{mysql.server}, @code{myisamchk} and @code{myisampack}.
+
+You can use option files to specify any long option that a program supports!
+Run the program with @code{--help} to get a list of available options.
+
+An option file can contain lines of the following forms:
+
+@table @code
+@item #comment
+Comment lines start with @samp{#} or @samp{;}. Empty lines are ignored.
+
+@item [group]
+@code{group} is the name of the program or group for which you want to set
+options. After a group line, any @code{option} or @code{set-variable} lines
+apply to the named group until the end of the option file or another group
+line is given.
+
+@item option
+This is equivalent to @code{--option} on the command line.
+
+@item option=value
+This is equivalent to @code{--option=value} on the command line.
+
+@item set-variable = variable=value
+This is equivalent to @code{--set-variable variable=value} on the command line.
+This syntax must be used to set a @code{mysqld} variable.
+@end table
+
+The @code{client} group allows you to specify options that apply to all
+@strong{MySQL} clients (not @code{mysqld}). This is the perfect group to use
+to specify the password you use to connect to the server. (But make
+sure the option file is readable and writable only to yourself.)
+
+Note that for options and values, all leading and trailing blanks are
+automatically deleted. You may use the escape sequences @samp{\b},
+@samp{\t}, @samp{\n}, @samp{\r}, @samp{\\} and @samp{\s} in your value string
+(@samp{\s} == blank).
+
+Here is a typical global option file:
+
+@example
+[client]
+port=3306
+socket=/tmp/mysql.sock
+
+[mysqld]
+port=3306
+socket=/tmp/mysql.sock
+set-variable = key_buffer_size=16M
+set-variable = max_allowed_packet=1M
+
+[mysqldump]
+quick
+@end example
+
+Here is typical user option file:
+
+@example
+[client]
+# The following password will be sent to all standard MySQL clients
+password=my_password
+
+[mysql]
+no-auto-rehash
+@end example
+
+@tindex .my.cnf file
+If you have a source distribution, you will find sample configuration
+files named @file{my-xxxx.cnf} in the @file{support-files} directory.
+If you have a binary distribution, look in the @file{DIR/share/mysql}
+directory, where @code{DIR} is the pathname to the @strong{MySQL}
+installation directory (typically @file{/usr/local/mysql}). Currently
+there is sample configuration files for small, medium, large and very
+large systems. You can copy @file{my-xxxx.cnf} to your home directory
+(rename the copy to @file{.my.cnf}) to experiment with this.
+
+To tell a @strong{MySQL} program not to read any option files, specify
+@code{--no-defaults} as the first option on the command line. This
+@strong{MUST} be the first option or it will have no effect!
+If you want to check which options are used, you can give the option
+@code{--print-defaults} as the first option.
+
+If you want to force the use of a specific config file, you can use the option
+@code{--defaults-file=full-path-to-default-file}. If you do this, only the
+specified file will be read.
+
+Note for developers: Option file handling is implemented simply by
+processing all matching options (i.e., options in the appropriate group)
+before any command line arguments. This works nicely for programs that use
+the last instance of an option that is specified multiple times. If you have
+an old program that handles multiply-specified options this way but doesn't
+read option files, you need add only two lines to give it that capability.
+Check the source code of any of the standard @strong{MySQL} clients to see
+how to do this.
+
+@node Upgrade, , Post-installation, Installing
+@section Is there anything special to do when upgrading/downgrading MySQL?
+
+You can always move the @strong{MySQL} form and data files between
+different versions on the same architecture as long as you have the same
+base version of @strong{MySQL}. The current base version is
+3. If you change the character set when running @strong{MySQL} (which may
+also change the sort order), you must run @code{myisamchk -r -q} on all
+tables. Otherwise your indexes may not be ordered correctly.
+
+If you are paranoid and/or afraid of new versions, you can always rename your
+old @code{mysqld} to something like @code{mysqld}-'old-version-number'. If
+your new @code{mysqld} then does something unexpected, you can simply shut it
+down and restart with your old @code{mysqld}!
+
+When you do an upgrade you should also backup your old databases, of course.
+Sometimes it's good to be a little paranoid!
+
+After an upgrade, if you experience problems with recompiled client programs,
+like @code{Commands out of sync} or unexpected core dumps, you probably have
+used an old header or library file when compiling your programs. In this
+case you should check the date for your @file{mysql.h} file and
+@file{libmysqlclient.a} library to verify that they are from the new
+@strong{MySQL} distribution. If not, please recompile your programs!
+
+If you get some problems that the new @code{mysqld} server doesn't want to
+start or that you can't connect without a password, check that you don't
+have some old @file{my.cnf} file from your old installation! You can
+check this with: @code{program-name --print-defaults}. If this outputs
+anything other than the program name, you have an active @code{my.cnf}
+file that will may affect things!
+
+It is a good idea to rebuild and reinstall the @code{Msql-Mysql-modules}
+distribution whenever you install a new release of @strong{MySQL},
+particularly if you notice symptoms such as all your @code{DBI} scripts
+dumping core after you upgrade @strong{MySQL}.
+
+@menu
+* Upgrading-from-3.22:: Upgrading from a 3.22 version to 3.23
+* Upgrading-from-3.21:: Upgrading from a 3.21 version to 3.22
+* Upgrading-from-3.20:: Upgrading from a 3.20 version to 3.21
+* Upgrading-to-arch:: Upgrading to another architecture
+@end menu
+
+@cindex Compatibility, between MySQL versions
+@node Upgrading-from-3.22, Upgrading-from-3.21, Upgrade, Upgrade
+@subsection Upgrading from a 3.22 version to 3.23
+
+@strong{MySQL} 3.23 supports tables of the new @code{MyISAM} type and
+the old @code{ISAM} type. You don't have to convert your old tables to
+use these with 3.23. By default, all new tables will be created with
+type @code{MyISAM} (unless you start @code{mysqld} with the
+@code{--default-table-type=isam} option. You can change an @code{ISAM}
+table to a @code{MyISAM} table with @code{ALTER TABLE} or the Perl script
+@code{mysql_convert_table_format}.
+
+3.22 and 3.21 clients will work without any problems with a 3.23 server.
+
+The following lists what you have to watch out for when upgrading to 3.23:
+
+@itemize @bullet
+@item The default return type of @code{IF} will now depend on both arguments
+and not only the first argument.
+@item @code{AUTO_INCREMENT} will not work with negative numbers.
+@item @code{INNER} and @code{DELAYED} are now reserved words.
+@item @code{FLOAT(X)} is now a true floating point types and not a value with
+a fixed number of decimals.
+@item When declaring @code{DECIMAL(length,dec)} the length argument no
+longer includes a place for the sign or the decimal point.
+@item A @code{TIME} string must now be of one of the following formats:
+@code{[[[DAYS] [H]H:]MM:]SS[.fraction]} or
+@code{[[[[[H]H]H]H]MM]SS[.fraction]}
+@item @code{LIKE} now compares strings using the same character
+comparison rules as @code{'='}. If you require the old behavior, you
+can compile @strong{MySQL} with the @code{CXXFLAGS=-DLIKE_CMP_TOUPPER}
+flag.
+@item @code{REGEXP} is now case insensitive for normal (not binary) strings.
+@item When you check/repair tables you should use @code{CHECK TABLE}
+or @code{myisamchk} for @code{MyISAM} tables (@code{.MYI}) and
+@code{isamchk} for ISAM (@code{.ISM}) tables.
+@item If you want your @code{mysqldump}s to be compatible between
+@strong{MySQL} 3.22 and 3.23, you should not use the @code{--opt} or
+@code{--full} option to @code{mysqldump}.
+@item Check all your calls to @code{DATE_FORMAT()} to make sure there is a
+@samp{%} before each format character. (Later @strong{MySQL} 3.22
+version did allow this syntax.
+@item
+@code{mysql_fetch_fields_direct} is now a function (it was a macro) and
+it returns a pointer to a @code{MYSQL_FIELD} instead of a
+@code{MYSQL_FIELD}.
+@item
+@code{mysql_num_fields()} can no longer be used on a @code{MYSQL*} object (it's
+now a function that takes @code{MYSQL_RES*} as an argument. You should now
+use @code{mysql_field_count()} instead.
+@item
+In @code{MySQL} 3.22, the output of @code{SELECT DISTINCT ...} was
+almost always sorted. In 3.23, you must use @code{GROUP BY} or
+@code{ORDER BY} to obtain sorted output.
+@item
+@code{SUM()} now returns @code{NULL}, instead of 0, if there is no matching
+rows. This is according to ANSI SQL.
+@item
+New restricted words: @code{CASE, THEN, WHEN, ELSE and END}
+@item An @code{AND} or @code{OR} with @code{NULL} values will now return
+@code{NULL} instead of 0. This mostly affects queries that uses @code{NOT}
+on an @code{AND/OR} expression as @code{NOT NULL} = @code{NULL}.
+@end itemize
+
+@cindex Compatibility, between MySQL versions
+@node Upgrading-from-3.21, Upgrading-from-3.20, Upgrading-from-3.22, Upgrade
+@subsection Upgrading from a 3.21 version to 3.22
+
+Nothing that affects compatibility has changed between 3.21 and 3.22. The
+only pitfall is that new tables that are created with @code{DATE} type
+columns will use the new way to store the date. You can't access these new
+fields from an old version of @code{mysqld}.
+
+After installing @strong{MySQL} 3.22, you should start the new server and
+then run the @code{mysql_fix_privilege_tables} script. This will add the new
+privileges that you need to use the @code{GRANT} command. If you forget
+this, you will get @code{Access denied} when you try to use @code{ALTER
+TABLE}, @code{CREATE INDEX} or @code{DROP INDEX}. If your @strong{MySQL} root
+user requires a password, you should give this as an argument to
+@code{mysql_fix_privilege_tables}.
+
+The C API interface to @code{mysql_real_connect()} has changed. If you have
+an old client program that calls this function, you must place a @code{0} for
+the new @code{db} argument (or recode the client to send the @code{db}
+element for faster connections). You must also call @code{mysql_init()}
+before calling @code{mysql_real_connect()}! This change was done to allow
+the new @code{mysql_options()} function to save options in the @code{MYSQL}
+handler structure.
+
+The @code{mysqld} variable @code{key_buffer} has changed names to
+@code{key_buffer_size}, but you can still use the old name in your
+startup files.
+
+@node Upgrading-from-3.20, Upgrading-to-arch, Upgrading-from-3.21, Upgrade
+@subsection Upgrading from a 3.20 version to 3.21
+
+If you are running a version older than 3.20.28 and want to
+switch to 3.21.x, you need to do the following:
+
+You can start the @code{mysqld} 3.21 server with @code{safe_mysqld
+--old-protocol} to use it with clients from the 3.20 distribution.
+In this case, the new client function @code{mysql_errno()} will not
+return any server error, only @code{CR_UNKNOWN_ERROR}, (but it
+works for client errors) and the server uses the old password() checking
+rather than the new one.
+
+If you are @strong{NOT} using the @code{--old-protocol} option to
+@code{mysqld}, you will need to make the following changes:
+
+@itemize @bullet
+@item
+All client code must be recompiled. If you are using ODBC, you must get
+the new @strong{MyODBC} 2.x driver.
+@item
+The script @code{scripts/add_long_password} must be run to convert the
+@code{Password} field in the @code{mysql.user} table to @code{CHAR(16)}.
+@item
+All passwords must be reassigned in the @code{mysql.user} table (to get 62-bit
+rather than 31-bit passwords).
+@item
+The table format hasn't changed, so you don't have to convert any tables.
+@end itemize
+
+@strong{MySQL} 3.20.28 and above can handle the new @code{user} table format
+without affecting clients. If you have a @strong{MySQL} version earlier than
+3.20.28, passwords will no longer work with it if you convert the @code{user}
+table. So to be safe, you should first upgrade to at least 3.20.28 and then
+upgrade to 3.21.x.
+
+@cindex Protocol mismatch
+The new client code works with a 3.20.x @code{mysqld} server, so
+if you experience problems with 3.21.x, you can use the old 3.20.x server
+without having to recompile the clients again.
+
+If you are not using the @code{--old-protocol} option to @code{mysqld},
+old clients will issue the error message:
+
+@example
+ERROR: Protocol mismatch. Server Version = 10 Client Version = 9
+@end example
+
+The new Perl @code{DBI}/@code{DBD} interface also supports the old
+@code{mysqlperl} interface. The only change you have to make if you use
+@code{mysqlperl} is to change the arguments to the @code{connect()} function.
+The new arguments are: @code{host}, @code{database}, @code{user},
+@code{password} (the @code{user} and @code{password} arguments have changed
+places).
+@xref{Perl DBI Class, , Perl @code{DBI} Class}.
+
+The following changes may affect queries in old applications:
+
+@itemize @bullet
+@item
+@code{HAVING} must now be specified before any @code{ORDER BY} clause.
+@item
+The parameters to @code{LOCATE()} have been swapped.
+@item
+There are some new reserved words. The most notable are @code{DATE},
+@code{TIME} and @code{TIMESTAMP}.
+@end itemize
+
+@node Upgrading-to-arch, , Upgrading-from-3.20, Upgrade
+@subsection Upgrading to another architecture
+
+If you are using @strong{MySQL} 3.23, you can copy the @code{.frm}, the
+@code{.MYI} and the @code{.MYD} files between different architectures
+that support the same floating point format. (@strong{MySQL} takes care
+of any byte swapping issues).
+
+The @strong{MySQL} @code{ISAM} data @file{*.ISD} and the index files
+@file{*.ISM} files) are architecture-dependent and in some case
+OS-dependent. If you want to move your applications to another machine
+that has a different architecture or OS than your current machine, you
+should not try to move a database by simply copying the files to the
+other machine. Use @code{mysqldump} instead.
+
+By default, @code{mysqldump} will create a file full of SQL statements.
+You can then transfer the file to the other machine and feed it as input
+to the @code{mysql} client.
+
+Try @code{mysqldump --help} to see what options are available.
+If you are moving the data to a newer version of @strong{MySQL}, you should use
+@code{mysqldump --opt} with the newer version to get a fast, compact dump.
+
+The easiest (although not the fastest) way to move a database between two
+machines is to run the following commands on the machine on which the
+database is located:
+
+@example
+shell> mysqladmin -h 'other hostname' create db_name
+shell> mysqldump --opt db_name \
+ | mysql -h 'other hostname' db_name
+@end example
+
+If you want to copy a database from a remote machine over a slow network,
+you can use:
+
+@example
+shell> mysqladmin create db_name
+shell> mysqldump -h 'other hostname' --opt --compress db_name \
+ | mysql db_name
+@end example
+
+You can also store the result in a file, then transfer the file to the
+target machine and load the file into the database there. For example,
+you can dump a database to a file on the source machine like this:
+
+@example
+shell> mysqldump --quick db_name | gzip > db_name.contents.gz
+@end example
+
+(The file created in this example is compressed.) Transfer the file
+containing the database contents to the target machine and run these commands
+there:
+
+@example
+shell> mysqladmin create db_name
+shell> gunzip < db_name.contents.gz | mysql db_name
+@end example
+
+@cindex @code{mysqldump}
+@cindex @code{mysqlimport}
+You can also use @code{mysqldump} and @code{mysqlimport} to accomplish
+the database transfer.
+For big tables, this is much faster than simply using @code{mysqldump}.
+In the commands shown below, @code{DUMPDIR} represents the full pathname
+of the directory you use to store the output from @code{mysqldump}.
+
+First, create the directory for the output files and dump the database:
+
+@example
+shell> mkdir DUMPDIR
+shell> mysqldump --tab=DUMPDIR db_name
+@end example
+
+Then transfer the files in the @code{DUMPDIR} directory to some corresponding
+directory on the target machine and load the files into @strong{MySQL}
+there:
+
+@example
+shell> mysqladmin create db_name # create database
+shell> cat DUMPDIR/*.sql | mysql db_name # create tables in database
+shell> mysqlimport db_name DUMPDIR/*.txt # load data into tables
+@end example
+
+Also, don't forget to copy the @code{mysql} database, because that's where the
+grant tables (@code{user}, @code{db}, @code{host}) are stored. You may have
+to run commands as the @strong{MySQL} @code{root} user on the new machine
+until you have the @code{mysql} database in place.
+
+After you import the @code{mysql} database on the new machine, execute
+@code{mysqladmin flush-privileges} so that the server reloads the grant table
+information.
+
+@cindex Compatibility, with ANSI SQL
+@node Compatibility, Privilege system, Installing, Top
+@chapter How standards-compatible is MySQL?
+
+@menu
+* Extensions to ANSI:: @strong{MySQL} extensions to ANSI SQL92
+* Ansi mode:: Runnning @strong{MySQL} in ANSI mode
+* Differences from ANSI:: @strong{MySQL} differences compared to ANSI SQL92
+* Missing functions:: Functionality missing from @strong{MySQL}
+* Standards:: What standards does @strong{MySQL} follow?
+* Commit-rollback:: How to cope without @code{COMMIT}-@code{ROLLBACK}
+@end menu
+
+@node Extensions to ANSI, Ansi mode, Compatibility, Compatibility
+@section MySQL extensions to ANSI SQL92
+
+@strong{MySQL} includes some extensions that you probably will not find in
+other SQL databases. Be warned that if you use them, your code will not be
+portable to other SQL servers. In some cases, you can write code that
+includes @strong{MySQL} extensions, but is still portable, by using comments
+of the form @code{/*! ... */}. In this case, @strong{MySQL} will parse and
+execute the code within the comment as it would any other @strong{MySQL}
+statement, but other SQL servers will ignore the extensions. For example:
+
+@example
+SELECT /*! STRAIGHT_JOIN */ col_name FROM table1,table2 WHERE ...
+@end example
+
+If you add a version number after the @code{'!'}, the syntax will only be
+executed if the @strong{MySQL} version is equal or newer than the used
+version number:
+
+@example
+CREATE /*!32302 TEMPORARY */ TABLE (a int);
+@end example
+
+The above means that if you have 3.23.02 or newer, then @strong{MySQL} will use
+the @code{TEMPORARY} keyword.
+
+@strong{MySQL} extensions are listed below:
+
+@itemize @bullet
+@item
+The field types @code{MEDIUMINT}, @code{SET}, @code{ENUM} and the
+different @code{BLOB} and @code{TEXT} types.
+
+@item
+The field attributes @code{AUTO_INCREMENT}, @code{BINARY}, @code{NULL},
+@code{UNSIGNED} and @code{ZEROFILL}.
+
+@item
+All string comparisons are case insensitive by default, with sort
+ordering determined by the current character set (ISO-8859-1 Latin1 by
+default). If you don't like this, you should declare your columns with
+the @code{BINARY} attribute or use the @code{BINARY} cast, which causes
+comparisons to be done according to the ASCII order used on the
+@strong{MySQL} server host.
+
+@item
+@strong{MySQL} maps each database to a directory under the @strong{MySQL}
+data directory, and tables within a database to filenames in the database
+directory.
+This has two implications:
+
+@itemize @minus
+@item
+@cindex Database names, case sensitivity
+@cindex Table names, case sensitivity
+@cindex Case sensitivity, of database names
+@cindex Case sensitivity, of table names
+Database names and table names are case sensitive in @strong{MySQL} on
+operating systems that have case sensitive filenames (like most Unix
+systems). If you have a problem remembering table names, adopt a consistent
+convention, such as always creating databases and tables using lowercase
+names.
+
+@item
+Database, table, index, column or alias names may begin with a digit
+(but may not consist solely of digits).
+
+@item
+You can use standard system commands to backup, rename, move, delete and copy
+tables. For example, to rename a table, rename the @file{.MYD}, @file{.MYI}
+and @file{.frm} files to which the table corresponds.
+@end itemize
+
+@item
+In SQL statements, you can access tables from different databases
+with the @code{db_name.tbl_name} syntax. Some SQL servers provide
+the same functionality but call this @code{User space}.
+@strong{MySQL} dosen't support tablespaces like in:
+@code{create table ralph.my_table...IN my_tablespace}.
+
+@item
+@code{LIKE} is allowed on numeric columns.
+
+@item
+Use of @code{INTO OUTFILE} and @code{STRAIGHT_JOIN} in a @code{SELECT}
+statement. @xref{SELECT, , @code{SELECT}}.
+
+@item
+The @code{SQL_SMALL_RESULT} option in a @code{SELECT} statement.
+
+@item
+@code{EXPLAIN SELECT} to get a description on how tables are joined.
+
+@item
+Use of index names, indexes on a prefix of a field, and use of
+@code{INDEX} or @code{KEY} in a @code{CREATE TABLE}
+statement. @xref{CREATE TABLE, , @code{CREATE TABLE}}.
+
+@item
+Use of @code{TEMPORARY} or @code{IF NOT EXISTS} with @code{CREATE TABLE}.
+
+@item
+Use of @code{COUNT(DISTINCT list)} where 'list' is more than one element.
+
+@item
+Use of @code{CHANGE col_name}, @code{DROP col_name} or @code{DROP INDEX}
+in an @code{ALTER TABLE} statement. @xref{ALTER TABLE, , @code{ALTER TABLE}}.
+
+@item
+Use of @code{IGNORE} in an @code{ALTER TABLE} statement.
+
+@item
+Use of multiple @code{ADD}, @code{ALTER}, @code{DROP} or @code{CHANGE}
+clauses in an @code{ALTER TABLE} statement.
+
+@item
+Use of @code{DROP TABLE} with the keywords @code{IF EXISTS}.
+
+@item
+You can drop multiple tables with a single @code{DROP TABLE} statement.
+
+@item
+The @code{LIMIT} clause of the @code{DELETE} statement.
+
+@item
+The @code{DELAYED} clause of the @code{INSERT} and @code{REPLACE}
+statements.
+
+@item
+The @code{LOW_PRIORITY} clause of the @code{INSERT}, @code{REPLACE},
+@code{DELETE} and @code{UPDATE} statements.
+
+@cindex Oracle compatibility
+@cindex Compatibility, with Oracle
+@item
+Use of @code{LOAD DATA INFILE}. In many cases, this syntax is compatible with
+Oracle's @code{LOAD DATA INFILE}. @xref{LOAD DATA, , @code{LOAD DATA}}.
+
+@item
+The @code{OPTIMIZE TABLE} statement.
+@xref{OPTIMIZE TABLE, , @code{OPTIMIZE TABLE}}.
+
+@item
+The @code{SHOW} statement.
+@xref{SHOW, , @code{SHOW}}.
+
+@item
+Strings may be enclosed by either @samp{"} or @samp{'}, not just by @samp{'}.
+
+@item
+Use of the escape @samp{\} character.
+
+@item
+The @code{SET OPTION} statement. @xref{SET OPTION, , @code{SET OPTION}}.
+
+@item
+You don't need to name all selected columns in the @code{GROUP BY} part.
+This gives better performance for some very specific, but quite normal
+queries.
+@xref{Group by functions}.
+
+@item
+To make it easier for users that come from other SQL environments,
+@strong{MySQL} supports aliases for many functions. For example, all
+string functions support both ANSI SQL syntax and ODBC syntax.
+
+@item
+@strong{MySQL} understands the @code{||} and @code{&&} operators to mean
+logical OR and AND, as in the C programming language. In @strong{MySQL},
+@code{||} and @code{OR} are synonyms, as are @code{&&} and @code{AND}.
+Because of this nice syntax, @strong{MySQL} doesn't support
+the ANSI SQL @code{||} operator for string concatenation; use
+@code{CONCAT()} instead. Because @code{CONCAT()} takes any number
+of arguments, it's easy to convert use of the @code{||} operator to
+@strong{MySQL}.
+
+@item
+@code{CREATE DATABASE} or @code{DROP DATABASE}.
+@xref{CREATE DATABASE, , @code{CREATE DATABASE}}.
+
+@cindex PostgreSQL compatibility
+@cindex Compatibility, with PostgreSQL
+@item
+The @code{%} operator is a synonym for @code{MOD()}. That is,
+@code{N % M} is equivalent to @code{MOD(N,M)}. @code{%} is supported
+for C programmers and for compatibility with PostgreSQL.
+
+@item
+The @code{=}, @code{<>}, @code{<=} ,@code{<}, @code{>=},@code{>},
+@code{<<}, @code{>>}, @code{<=>}, @code{AND}, @code{OR} or @code{LIKE}
+operators may be used in column comparisons to the left of the
+@code{FROM} in @code{SELECT} statements. For example:
+
+@example
+mysql> SELECT col1=1 AND col2=2 FROM tbl_name;
+@end example
+
+@item
+The @code{LAST_INSERT_ID()} function.
+@xref{mysql_insert_id, , @code{mysql_insert_id()}}.
+
+@item
+The @code{REGEXP} and @code{NOT REGEXP} extended regular expression
+operators.
+
+@item
+@code{CONCAT()} or @code{CHAR()} with one argument or more than two
+arguments. (In @strong{MySQL}, these functions can take any number of
+arguments.)
+
+@item The @code{BIT_COUNT()}, @code{CASE}, @code{ELT()},
+@code{FROM_DAYS()}, @code{FORMAT()}, @code{IF()}, @code{PASSWORD()},
+@code{ENCRYPT()}, @code{md5()}, @code{ENCODE()}, @code{DECODE()},
+@code{PERIOD_ADD()}, @code{PERIOD_DIFF()}, @code{TO_DAYS()}, or
+@code{WEEKDAY()} functions.
+
+@item
+Use of @code{TRIM()} to trim substrings. ANSI SQL only supports removal
+of single characters.
+
+@item
+The @code{GROUP BY} functions @code{STD()}, @code{BIT_OR()} and
+@code{BIT_AND()}.
+
+@item
+Use of @code{REPLACE} instead of @code{DELETE} + @code{INSERT}.
+@xref{REPLACE, , @code{REPLACE}}.
+
+@item
+The @code{FLUSH flush_option} statement.
+
+@item
+The possiblity to set variables in a statement with @code{:=}:
+@example
+SELECT @@a:=SUM(total),@@b=COUNT(*),@@a/@@b AS avg FROM test_table;
+SELECT @@t1:=(@@t2:=1)+@@t3:=4,@@t1,@@t2,@@t3;
+@end example
+
+@end itemize
+
+@node Ansi mode, Differences from ANSI, Extensions to ANSI, Compatibility
+@section Runnning MySQL in ANSI mode
+
+If you start mysqld with the @code{--ansi} option, the following behaviour
+of @strong{MySQL} changes.
+
+@itemize @bullet
+@item
+@code{||} is string concatenation instead of @code{OR}.
+@item
+One can have any number of spaces between a function name and the '('. This
+makes also all function names reserved words.
+@item
+@code{"} will be an identifier quote character (like the @strong{MySQL}
+@code{`} quote character) and not a string quote character.
+@item
+@code{REAL} will be a synonym for @code{FLOAT} instead of a synonym of
+@code{DOUBLE}.
+@end itemize
+
+@node Differences from ANSI, Missing functions, Ansi mode, Compatibility
+@section MySQL differences compared to ANSI SQL92
+
+We try to make @strong{MySQL} follow the ANSI SQL standard and the
+ODBC SQL standard, but in some cases @strong{MySQL} does some things
+differently:
+
+@itemize @bullet
+@item
+@code{--} is only a comment if followed by a white space. @xref{Missing comments}.
+@item
+For @code{VARCHAR} columns, trailing spaces are removed when the value is
+stored. @xref{Bugs}.
+@item
+In some cases, @code{CHAR} columns are silently changed to @code{VARCHAR}
+columns. @xref{Silent column changes}.
+@item
+Privileges for a table is not automatically revoked when you delete a
+table. You must explicitly issue a @code{REVOKE} to revoke privileges for
+a table. @xref{GRANT, , @code{GRANT}}.
+@item
+@code{NULL AND FALSE} will evaluate to @code{NULL} and not to @code{FALSE}.
+This is because we don't think it's good to have to evaluate a lot of
+extra conditions in this case.
+@end itemize
+
+@node Missing functions, Standards, Differences from ANSI, Compatibility
+@section Functionality missing from MySQL
+
+The following functionality is missing in the current version of
+@strong{MySQL}. For a prioritized list indicating when new extensions may be
+added to @strong{MySQL}, you should consult
+@uref{http://www.mysql.com/documentation/manual.php?section=TODO, the online
+@strong{MySQL} TODO list}. That is the latest version of the TODO list in
+this manual. @xref{TODO}.
+
+@menu
+* Missing Sub-selects:: Sub-selects
+* Missing SELECT INTO TABLE:: @code{SELECT INTO TABLE}
+* Missing Transactions:: Transactions
+* Missing Triggers:: Triggers
+* Missing Foreign Keys:: Foreign Keys
+* Missing Views:: Views
+* Missing comments:: @samp{--} as the start of a comment
+@end menu
+
+@node Missing Sub-selects, Missing SELECT INTO TABLE, Missing functions, Missing functions
+@subsection Sub-selects
+
+The following will not yet work in @strong{MySQL}:
+
+@example
+SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);
+SELECT * FROM table1 WHERE id NOT IN (SELECT id FROM table2);
+@end example
+
+However, in many cases you can rewrite the query without a sub select:
+
+@example
+SELECT table1.* FROM table1,table2 WHERE table1.id=table2.id;
+SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id where table2.id IS NULL
+@end example
+
+For more complicated subqueries you can often create temporary tables
+to hold the subquery. In some cases, however this option will not
+work. The most frequently encountered of these cases arises with
+@code{DELETE} statements, for which standard SQL does not support joins
+(except in sub-selects). For this situation there are two options
+available until subqueries are supported by @strong{MySQL}.
+
+The first option is to use a procedural programming language (such as
+Perl or PHP) to submit a @code{SELECT} query to obtain the primary keys
+for the records to be deleted, and then use these values to construct
+the @code{DELETE} statement (@code{DELETE FROM ... WHERE ... IN (key1,
+key2, ...)}).
+
+The second option is to use interactive SQL to contruct a set of
+@code{DELETE} statements automatically, using the @strong{MySQL}
+extension @code{CONCAT()} (in lieu of the standard @code{||} operator).
+For example:
+
+@example
+SELECT CONCAT('DELETE FROM tab1 WHERE pkid = ', tab1.pkid, ';')
+ FROM tab1, tab2
+ WHERE tab1.col1 = tab2.col2;
+@end example
+
+You can place this query in a script file and redirect input from it to
+the @code{mysql} command-line interpreter, piping its output back to a
+second instance of the interpreter:
+
+@example
+prompt> mysql --skip-column-names mydb < myscript.sql | mysql mydb
+@end example
+
+@strong{MySQL} only supports @code{INSERT ... SELECT ...} and
+@code{REPLACE ... SELECT ...} Independent sub-selects will be probably
+be available in 3.24.0. You can now use the function @code{IN()} in
+other contexts, however.
+
+@node Missing SELECT INTO TABLE, Missing Transactions, Missing Sub-selects, Missing functions
+@subsection @code{SELECT INTO TABLE}
+
+@strong{MySQL} doesn't yet support the Oracle SQL extension:
+@code{SELECT ... INTO TABLE ...}. @strong{MySQL} supports instead the
+ANSI SQL syntax @code{INSERT INTO ... SELECT ...}, which is basically
+the same thing.
+
+Alternatively, you can use @code{SELECT INTO OUTFILE...} or @code{CREATE
+TABLE ... SELECT} to solve your problem.
+
+@node Missing Transactions, Missing Triggers, Missing SELECT INTO TABLE, Missing functions
+@subsection Transactions
+
+As @strong{MySQL} does nowadays support transactions, the following
+discussion is only valid if you are only using the non-transaction-safe
+table types. @xref{COMMIT}.
+
+The question is often asked, by the curious and the critical, ``Why is
+@strong{MySQL} not a transactional database?'' or ``Why does @strong{MySQL}
+not support transactions?''
+
+@strong{MySQL} has made a conscious decision to support another paradigm
+for data integrity, ``atomic operations.'' It is our thinking and
+experience that atomic operations offer equal or even better integrity
+with much better performance. We, nonetheless, appreciate and understand
+the transactional database paradigm and plan, within the next few releases,
+to introduce transaction safe tables on a per table basis. We will be
+giving our users the possibility to decide if they need the speed of
+atomic operations or if they need to use transactional features in their
+applications.
+
+How does one use the features of @strong{MySQL} to maintain rigorous integrity
+and how do these features compare with the transactional paradigm?
+
+First, in the transactional paradigm, if your applications are written
+in a way that is dependent on the calling of ``rollback'' instead of
+``commit'' in critical situations, then transactions are more
+convenient. Moreover, transactions ensure that unfinished updates or
+corrupting activities are not commited to the database; the server is
+given the opportunity to do an automatic rollback and your database is
+saved.
+
+@strong{MySQL}, in almost all cases, allows you to solve for potential
+problems by including simple checks before updates and by running simple
+scripts that check the databases for inconsistencies and automatically
+repair or warn if such occurs. Note that just by using the
+@strong{MySQL} log or even adding one extra log, one can normally fix
+tables perfectly with no data integrity loss.
+
+Moreover, ``fatal'' transactional updates can be rewritten to be
+atomic. In fact,we will go so far as to say that all integrity problems
+that transactions solve can be done with @code{LOCK TABLES} or atomic updates,
+ensuring that you never will get an automatic abort from the database,
+which is a common problem with transactional databases.
+
+Not even transactions can prevent all loss if the server goes down. In
+such cases even a transactional system can lose data. The difference
+between different systems lies in just how small the time-lap is where
+they could lose data. No system is 100% secure, only ``secure
+enough.'' Even Oracle, reputed to be the safest of transactional
+databases, is reported to sometimes lose data in such situations.
+
+To be safe with @strong{MySQL}, you only need to have backups and have
+the update logging turned on. With this you can recover from any
+situation that you could with any transactional database. It is, of
+course, always good to have backups, independent of which database you
+use.
+
+The transactional paradigm has its benefits and its drawbacks. Many
+users and application developers depend on the ease with which they can
+code around problems where an ``abort'' appears or is necessary, and they
+may have to do a little more work with @strong{MySQL} to either think
+differently or write more. If you are new to the atomic operations
+paradigm, or more familiar or more comfortable with transactions, do not
+jump to the conclusion that @strong{MySQL} has not addressed these
+issues. Reliability and integrity are foremost in our minds. Recent
+estimates are that there are more than 1,000,000 mysqld servers
+currently running, many of which are in production environments. We
+hear very, very seldom from our users that they have lost any data, and
+in almost all of those cases user error is involved. This is in our
+opinion the best proof of @strong{MySQL}'s stability and reliability.
+
+Lastly, in situations where integrity is of highest importance,
+@strong{MySQL}'s current features allow for transaction-level or better
+reliability and integrity. If you lock tables with @code{LOCK TABLES}, all
+updates will stall until any integrity checks are made. If you only obtain
+a read lock (as opposed to a write lock), then reads and inserts are
+still allowed to happen. The new inserted records will not be seen by
+any of the clients that have a @code{READ} lock until they relaease their read
+locks. With @code{INSERT DELAYED} you can queue inserts into a local queue,
+until the locks are released, without having to have the client wait
+for the insert to complete.
+
+``Atomic,'' in the sense that we mean it, is nothing magical. It only means
+that you can be sure that while each specific update is running no other
+user can interfere with it and that there will never be an automatic
+rollback (which can happen on transaction based systems if you are not
+very careful). @strong{MySQL} also guarantees that there will not be
+any dirty reads. You can find some example of how to write atomic updates
+in the in the commit-rollback section. @xref{Commit-rollback}.
+
+We have thought quite a bit about integrity and performance and we
+believe that our atomic operations paradigm allows for both high
+reliability and extremely high performance, on the order of three to
+five times the speed of the fastest and most optimally tuned of
+transactional databases. We didn't leave out transactions because they
+are hard to do; The main reason we went with atomic operations as
+opposed to transactions is that by doing this we could apply many speed
+optimizations that would not otherwise have been possible.
+
+Many of our users who have speed foremost in their minds are not at all
+concerned about transactions. For them transactions are not an
+issue. For those of our users who are concerned with or have wondered
+about transactions vis a vis @strong{MySQL}, there is a ``@strong{MySQL}
+way'' as we have outlined above. For those where safety is more important
+than speed, we recommend them to use the @code{BDB} tables for all their
+critical data. @xref{BDB}.
+
+One final note: we are currently working on a safe replication schema
+that we believe to be better than any commercial replication system we
+know of. This system will work most reliably under the atomic
+operations, non-transactional, paradigm. Stay tuned.
+
+@node Missing Triggers, Missing Foreign Keys, Missing Transactions, Missing functions
+@subsection Stored procedures and triggers
+
+A stored procedure is a set of SQL commands that can be compiled and stored
+in the server. Once this has been done, clients don't need to keep reissuing
+the entire query but can refer to the stored procedure. This provides better
+performance because the query has to be parsed only once and less information
+needs 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 a particular event
+occurs. For example, you can install a stored procedure that is triggered
+each time a record is deleted from a transaction table and that automatically
+deletes the corresponding customer from a customer table when all his
+transactions are deleted.
+
+The planned update language will be able to
+handle stored procedures, but without triggers. Triggers usually slow
+down everything, even queries for which they are not needed.
+
+To see when @strong{MySQL} might get stored procedures, see @ref{TODO}.
+
+@node Missing Foreign Keys, Missing Views, Missing Triggers, Missing functions
+@subsection Foreign Keys
+
+Note that foreign keys in SQL are not used to join tables, but are used
+mostly for checking referential integrity. If you want to get results from
+multiple tables from a @code{SELECT} statement, you do this by joining
+tables!
+
+@example
+SELECT * from table1,table2 where table1.id = table2.id;
+@end example
+@xref{JOIN, , @code{JOIN}}. @xref{example-Foreign keys}.
+
+The @code{FOREIGN KEY} syntax in @strong{MySQL} exists only for compatibility
+with other SQL vendors' @code{CREATE TABLE} commands; it doesn't do
+anything. The @code{FOREIGN KEY} syntax without @code{ON DELETE ...} is
+mostly used for documentation purposes. Some ODBC applications may use this
+to produce automatic @code{WHERE} clauses, but this is usually easy to
+override. @code{FOREIGN KEY} is sometimes used as a constraint check, but
+this check is unnecessary in practice if rows are inserted into the tables in
+the right order. @strong{MySQL} only supports these clauses because some
+applications require them to exist (regardless of whether or not they
+work!).
+
+In @strong{MySQL}, you can work around the problem of @code{ON DELETE
+...} not being implemented by adding the appropriate @code{DELETE} statement to
+an application when you delete records from a table that has a foreign key.
+In practice this is as quick (in some cases quicker) and much more portable
+than using foreign keys.
+
+In the near future we will extend the @code{FOREIGN KEY} implementation so
+that at least the information will be saved in the table specification file
+and may be retrieved by @code{mysqldump} and ODBC.
+
+@menu
+* Broken Foreign KEY:: Reasons NOT to use foreign keys
+@end menu
+
+@node Broken Foreign KEY, , Missing Foreign Keys, Missing Foreign Keys
+@subsubsection Reasons NOT to use foreign keys
+
+There are so many problems with @code{FOREIGN KEY}s that we don't
+know where to start:
+
+@itemize @bullet
+@item
+Foreign keys make life very complicated, because the foreign key definitions
+must be stored in a database and implementing them would destroy the whole
+``nice approach'' of using files that can be moved, copied and removed.
+
+@item
+The speed impact is terrible for @code{INSERT} and @code{UPDATE} statements,
+and in this case almost all @code{FOREIGN KEY} checks are useless because you
+usually insert records in the right tables in the right order, anyway.
+
+@item
+There is also a need to hold locks on many more tables when updating one
+table, because the side effects can cascade through the entire database. It's
+MUCH faster to delete records from one table first and subsequently delete
+them from the other tables.
+
+@item
+You can no longer restore a table by doing a full delete from
+the table and then restoring all records (from a new source or from a backup).
+
+@item
+If you have foreign keys you can't dump and restore tables unless you do so
+in a very specific order.
+
+@item
+It's very easy to do ``allowed'' circular definitions that make the
+tables impossible to recreate each table with a single create statement,
+even if the definition works and is usable.
+@end itemize
+
+The only nice aspect of @code{FOREIGN KEY} is that it gives ODBC and some
+other client programs the ability to see how a table is connected and to use
+this to show connection diagrams and to help in building applicatons.
+
+@strong{MySQL} will soon store @code{FOREIGN KEY} definitions so that
+a client can ask for and receive an answer how the original connection was
+made. The current @file{.frm} file format does not have any place for it.
+
+@node Missing Views, Missing comments, Missing Foreign Keys, Missing functions
+@subsection Views
+
+@strong{MySQL} doesn't support views, but this is on the TODO.
+
+@node Missing comments, , Missing Views, Missing functions
+@subsection @samp{--} as the start of a comment
+
+Some other SQL databases use @samp{--} to start comments. @strong{MySQL}
+has @samp{#} as the start comment character, even if the @code{mysql}
+command line tool removes all lines that start with @samp{--}.
+You can also use the C comment style @code{/* this is a comment */} with
+@strong{MySQL}.
+@xref{Comments}.
+
+@strong{MySQL} 3.23.3 and above supports the @samp{--} comment style
+only if the comment is followed by a space. This is because this
+degenerate comment style has caused many problems with automatically
+generated SQL queries that have used something like the following code,
+where we automatically insert the value of the payment for
+@code{!payment!}:
+
+@example
+UPDATE tbl_name SET credit=credit-!payment!
+@end example
+
+What do you think will happen when the value of @code{payment} is negative?
+
+Because @code{1--1} is legal in SQL, we think it is terrible that
+@samp{--} means start comment.
+
+In @strong{MySQL} 3.23 you can however use: @code{1-- This is a comment}
+
+The following discussing only concerns you if you are running an
+@strong{MySQL} version earlier than 3.23:
+
+If you have a SQL program in a text file that contains @samp{--} comments
+you should use:
+
+@example
+shell> replace " --" " #" < text-file-with-funny-comments.sql \
+ | mysql database
+@end example
+
+instead of the usual:
+
+@example
+shell> mysql database < text-file-with-funny-comments.sql
+@end example
+
+You can also edit the command file ``in place'' to change the @samp{--}
+comments to @samp{#} comments:
+
+@example
+shell> replace " --" " #" -- text-file-with-funny-comments.sql
+@end example
+
+Change them back with this command:
+
+@example
+shell> replace " #" " --" -- text-file-with-funny-comments.sql
+@end example
+
+@node Standards, Commit-rollback, Missing functions, Compatibility
+@section What standards does MySQL follow?
+
+Entry level SQL92. ODBC level 0-2.
+
+@node Commit-rollback, , Standards, Compatibility
+@section How to cope without @code{COMMIT}/@code{ROLLBACK}
+
+The following mostly apply only for @code{ISAM}, @code{MyISAM} and
+@code{HEAP} tables; If you only use transaction safe tables (@code{BDB}
+tables) in an a update you can do @code{COMMIT} and @code{ROLLBACK} also
+with @code{MySQL}. @xref{COMMIT}.
+
+The problem with handling @code{COMMIT}-@code{ROLLBACK} efficiently with
+the above table types would require a completely different table layout
+than @strong{MySQL} uses today. The table type would also need extra
+threads that do automatic cleanups on the tables and the disk usage
+would be much higher. This would these table types about 2-4 times
+slower than they are today.
+
+For the moment, we are much more for implementing the SQL server
+language (something like stored procedures). With this you would very
+seldom really need @code{COMMIT}-@code{ROLLBACK.} This would also give much
+better performance.
+
+Loops that need transactions normally can be coded with the help of
+@code{LOCK TABLES}, and you don't need cursors when you can update records
+on the fly.
+
+We at TcX had a greater need for a real fast database than a 100%
+general database. Whenever we find a way to implement these features without
+any speed loss, we will probably do it. For the moment, there are many more
+important things to do. Check the TODO for how we prioritize things at
+the moment. (Customers with higher levels of support can alter this, so
+things may be reprioritized.)
+
+The current problem is actually @code{ROLLBACK}. Without
+@code{ROLLBACK}, you can do any kind of @code{COMMIT} action with
+@code{LOCK TABLES}. To support @code{ROLLBACK} with the above table
+types, @strong{MySQL} would have to be changed to store all old records
+that were updated and revert everything back to the starting point if
+@code{ROLLBACK} was issued. For simple cases, this isn't that hard to do
+(the current @code{isamlog} could be used for this purpose), but it
+would be much more difficult to implement @code{ROLLBACK} for
+@code{ALTER/DROP/CREATE TABLE}.
+
+To avoid using @code{ROLLBACK}, you can use the following strategy:
+
+@enumerate
+@item
+Use @code{LOCK TABLES ...} to lock all the tables you want to access.
+@item
+Test conditions.
+@item
+Update if everything is okay.
+@item
+Use @code{UNLOCK TABLES} to release your locks.
+@end enumerate
+
+This is usually a much faster method than using transactions with possible
+@code{ROLLBACK}s, although not always. The only situation this solution
+doesn't handle is when someone kills the threads in the middle of an
+update. In this case, all locks will be released but some of the updates may
+not have been executed.
+
+You can also use functions to update records in a single operation.
+You can get a very efficient application by using the following techniques:
+
+@itemize @bullet
+@item
+Modify fields relative to their current value
+
+@item
+Update only those fields that actually have changed
+@end itemize
+
+For example, when we are doing updates to some customer information, we
+update only the customer data that have changed and test only that none of
+the changed data, or data that depend on the changed data, have changed
+compared to the original row. The test for changed data is done with the
+@code{WHERE} clause in the @code{UPDATE} statement. If the record wasn't
+updated, we give the client a message: "Some of the data you have changed
+have been changed by another user". Then we show the old row versus the new
+row in a window, so the user can decide which version of the customer record
+he should use.
+
+This gives us something that is similar to ``column locking'' but is actually
+even better, because we only update some of the columns, using values that
+are relative to their current values. This means that typical @code{UPDATE}
+statements look something like these:
+
+@example
+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_us+'new_money'
+ WHERE
+ customer_id=id AND address='old address' AND phone='old phone';
+@end example
+
+As you can see, this is very efficient and works even if another client has
+changed the values in the @code{pay_back} or @code{money_he_owes_us} columns.
+
+@findex mysql_insert_id()
+@findex LAST_INSERT_ID()
+In many cases, users have wanted @code{ROLLBACK} and/or @code{LOCK
+TABLES} for the purpose of managing unique identifiers for some tables. This
+can be handled much more efficiently by using an @code{AUTO_INCREMENT} column
+and either the SQL function @code{LAST_INSERT_ID()} or the C API function
+@code{mysql_insert_id()}. @xref{mysql_insert_id, , @code{mysql_insert_id()}}.
+
+@cindex Row-level locking
+At MySQL AB, we have never had any need for row-level locking because we have
+always been able to code around it. Some cases really need row
+locking, but they are very few. If you want row-level locking, you
+can use a flag column in the table and do something like this:
+
+@example
+UPDATE tbl_name SET row_flag=1 WHERE id=ID;
+@end example
+
+@strong{MySQL} returns 1 for the number of affected rows if the row was
+found and @code{row_flag} wasn't already 1 in the original row.
+
+You can think of it as @strong{MySQL} changed the above query to:
+
+@example
+UPDATE tbl_name SET row_flag=1 WHERE id=ID and row_flag <> 1;
+@end example
+
+@node Privilege system, Reference, Compatibility, Top
+@chapter The MySQL access privilege system
+
+@strong{MySQL} has an advanced but non-standard security/privilege
+system. This section describes how it works.
+
+@menu
+* General security:: General security
+* Security:: How to make @strong{MySQL} secure against crackers
+* What Privileges:: What the privilege system does
+* User names:: @strong{MySQL} user names and passwords
+* Connecting:: Connecting to the @strong{MySQL} server
+* Password security:: Keeping your password secure
+* Privileges provided:: Privileges provided by @strong{MySQL}
+* Privileges:: How the privilege system works
+* Connection access:: Access control, stage 1: Connection verification
+* Request access:: Access control, stage 2: Request verification
+* Privilege changes:: When privilege changes take effect
+* Default privileges:: Setting up the initial @strong{MySQL} privileges
+* Adding users:: Adding new user privileges to @strong{MySQL}
+* Passwords:: How to set up passwords
+* Access denied:: Causes of @code{Access denied} errors
+@end menu
+
+@node General security, Security, Privilege system, Privilege system
+@section General security
+
+Anyone using @strong{MySQL} on a computer connected to the Internet
+should read this section to avoid the most common security mistakes.
+
+In discussing ``security'' we emphasize the necessity of fully protecting the
+entire server host (not simply the @strong{MySQL} server) against all types
+of applicable attacks: eavesdropping, altering, playback and Denial of
+Service. We do not cover all aspects of availability and fault tolerance
+here.
+
+@strong{MySQL} uses Access Control Lists (ACLs) security for all
+connections, queries, and other operations which a user may attempt to
+perform. There is also some support for SSL encrypted connections
+between @strong{MySQL} clients and servers. Many of the concepts
+discussed here are not specific to @strong{MySQL} at all; the same
+general ideas apply to almost all applications.
+
+When running @strong{MySQL}, follow these guidelines whenever possible:
+
+@itemize @bullet
+@item
+Learn the @strong{MySQL} access privilege system. The @code{GRANT} and
+@code{REVOKE} commands are used for restricting access to @strong{MySQL}. Do
+not grant any more privileges than necessary. Never grant privileges to all
+hosts.
+
+Checklist:
+@itemize @bullet
+@item
+Try @code{mysql -u root}. If you are able to connect successfully to the
+server without being asked for a password, you have problems. Any user (not
+just root) can connect to your @strong{MySQL} server with full privileges!
+Review the @strong{MySQL} installation instructions, paying particular
+attention to the item about setting a @code{root} password.
+@item
+Use the command @code{SHOW GRANTS} and check to see who has access to
+what. Remove those privileges which are not necessary using the @code{REVOKE}
+command.
+@end itemize
+
+@item
+Do not keep any plain-text passwords in your database. When your
+computer becomes compromised, the intruder can take the full list of
+passwords and use them. Instead use @code{MD5()} or another one-way
+hashing function.
+@item
+Do not use passwords from dictionaries. There are special programs to
+break them. Even passwords like ``xfish98'' are very bad. Much better is
+``duag98'' which contains the same word ``fish'' but typed one key to the
+left on a standard QWERTY keyboard. Another method is to use ``Mhall'' which
+is taken from first characters of sentence ``Mary had a little lamb''. This
+is easy to remember and type, but hard to guess for someone who does not know
+it.
+@item
+Invest in a firewall. This protects from at least 50% of all types of
+exploits in any software. Put @strong{MySQL} behind the firewall or in
+a demilitarized zone (DMZ).
+
+Checklist:
+@itemize @bullet
+@item
+Try to scan your ports from the Internet using a tool such as
+@code{nmap}. @strong{MySQL} uses port 3306 by default. This port should
+be inaccessible from untrusted hosts. Another simple way to check whether or not
+your @strong{MySQL} port is open is to type @code{telnet
+server_host 3306} from some remote machine, where
+@code{server_host} is the hostname of your @strong{MySQL}
+server. If you get a connection and some garbage characters, the port is
+open, and should be closed on your firewall or router, unless you really
+have a good reason to keep it open. If @code{telnet} just hangs,
+everything is OK, the port is blocked.
+@end itemize
+
+@item
+Do not trust any data entered by your users. They can try to trick your
+code by entering special or escaped character sequences in web forms,
+URLs, or whatever application you have built. Be sure that your
+application remains secure if user enters something like @code{; DROP
+DATABASE mysql;}. This is an extreme example, but large security leaks
+and data loss may occur as a result of hackers using similar techniques,
+if you do not prepare for them.
+
+Also remember to check numeric data. A common mistake is to protect only
+strings. Sometimes people think that if a database contains only publicly
+available data that it need not be protected. This is incorrect. At least
+Denial-of-Service type attacks can be performed on such
+databases. The simplest way to protect from this type of attack is to use
+apostrophes around the numeric constants: @code{SELECT * FROM table
+WHERE ID='234'} instead of @code{SELECT * FROM table WHERE ID=234}.
+@strong{MySQL} automatically converts this string to a number and
+meanwhile strips all non-numeric symbols from it.
+
+Checklist:
+@itemize @bullet
+@item
+All WWW applications:
+@itemize @bullet
+@item
+Try to enter @samp{'} and @samp{"} in all your Web forms. If you get any kind
+of @strong{MySQL} error, investigate the problem right away.
+@item
+Try to modify any dynamic URLs by adding @code{%22} (@samp{"}), @code{%23}
+(@samp{#}) and @code{%27} (@samp{'}) in the URL.
+@item
+Try to modify datatypes in dynamic URLs from numeric ones to character
+ones containing characters from previous example. Your application
+should be safe against this and similar attacks.
+@item
+Try to enter characters, spaces, special symbols instead of numbers in
+numeric fields. Your application should remove them before passing them to
+@strong{MySQL} or your application should generate an error. Passing
+unchecked values to @strong{MySQL} is very dangerous!
+@item
+Check data sizes before passing them to @strong{MySQL}.
+@item
+Consider having your application connect to the database using a
+different user name than the one you use for administrative purposes. Do not give
+your applications any more access privileges than what they need.
+@end itemize
+@item
+Users of PHP:
+@itemize @bullet
+@item
+Check out the @code{addslashes()} function.
+@end itemize
+@item
+Users of @strong{MySQL} C API:
+@itemize @bullet
+@item
+Check out the @code{mysql_escape()} API call.
+@end itemize
+@item
+Users of @strong{MySQL}++:
+@itemize @bullet
+@item
+Check out the @code{escape} and @code{quote} modifiers for query streams.
+@end itemize
+@item
+Users of Perl DBI
+@itemize @bullet
+@item
+Check out the @code{quote()} method.
+@end itemize
+@end itemize
+
+@item
+Do not transmit plain (unencrypted) data over the Internet. These data are
+accessible to everyone who has the time and ability to intercept it and use
+it for their own purposes. Instead, use an encrypted protocol such as SSL or
+SSH. @strong{MySQL} supports internal SSL connections as of version 3.23.9.
+SSH port-forwarding can be used to create an encrypted (and compressed)
+tunnel for the communication.
+@item
+Learn to use the @code{tcpdump} and @code{strings} utilities. For most cases,
+you can check whether or not @strong{MySQL} data streams are unencrypted
+by issuing a command like the following:
+
+@example
+shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings
+@end example
+
+(This works under Linux and should work with small modifications under
+other systems). Warning: If you do not see data this doesn't always
+actually mean that it is encrypted. If you need high security, you should
+consult with a security expert.
+@end itemize
+
+@node Security, What Privileges, General security, Privilege system
+@section How to make MySQL secure against crackers
+
+When you connect to a @strong{MySQL} server, you normally should use a
+password. The password is not transmitted in clear text over the
+connection.
+
+All other information is transferred as text that can be read by anyone
+that is able to watch the connection. If you are concerned about this,
+you can use the compressed protocol (in @strong{MySQL} 3.22 and above)
+to make things much harder. To make things even more secure you should
+use @code{ssh} (see @uref{http://www.cs.hut.fi/ssh}). With this, you
+can get an encrypted TCP/IP connection between a @strong{MySQL} server
+and a @strong{MySQL} client.
+
+To make a @strong{MySQL} system secure, you should strongly consider the
+following suggestions:
+
+@itemize @bullet
+@item
+Use passwords for all @strong{MySQL} users. Remember that anyone can log in
+as any other person as simply as @code{mysql -u other_user db_name} if
+@code{other_user} has no password. It is common behavior with client/server
+applications that the client may specify any user name. You can change the
+password of all users by editing the @code{mysql_install_db} script before
+you run it, or only the password for the @strong{MySQL} @code{root} user like
+this:
+
+@example
+shell> mysql -u root mysql
+mysql> UPDATE user SET Password=PASSWORD('new_password')
+ WHERE user='root';
+mysql> FLUSH PRIVILEGES;
+@end example
+
+@item
+Don't run the @strong{MySQL} daemon as the Unix @code{root} user.
+It is very dangerous as any user with @code{FILE} privileges will be able to
+create files
+as @code{root} (e.g. @code{~root/.bashrc}). To prevent this
+@code{mysqld} will refuse to run as @code{root} unless it is specified
+directly via @code{--user=root} option.
+
+@code{mysqld} can be run as any user instead. You can also create a new
+Unix user @code{mysql} to make everything even more secure. If you run
+@code{mysqld} as another Unix user, you don't need to change the
+@code{root} user name in the @code{user} table, because @strong{MySQL}
+user names have nothing to do with Unix user names. You can edit the
+@code{mysql.server} script to start @code{mysqld} as another Unix user.
+Normally this is done with the @code{su} command. For more details, see
+@ref{Changing MySQL user, , Changing @strong{MySQL} user}.
+
+@item
+If you put a password for the Unix @code{root} user in the @code{mysql.server}
+script, make sure this script is readable only by @code{root}.
+
+@item
+Check that the Unix user that @code{mysqld} runs as is the only user with
+read/write privileges in the database directories.
+
+@item
+On Unix platforms, do not run @code{mysqld} as root unless you really
+need to. Consider creating a user named @code{mysql} for that purpose.
+
+@item
+Don't give the @strong{process} privilege to all users. The output of
+@code{mysqladmin processlist} shows the text of the currently executing
+queries, so any user who is allowed to execute that command might be able to
+see if another user issues an @code{UPDATE user SET
+password=PASSWORD('not_secure')} query.
+
+@code{mysqld} reserves an extra connection for users who have the
+@strong{process} privilege, so that a @strong{MySQL} @code{root} user can log
+in and check things even if all normal connections are in use.
+
+@item
+Don't give the @strong{file} privilege to all users. Any user that has this
+privilege can write a file anywhere in the file system with the privileges of
+the @code{mysqld} daemon! To make this a bit safer, all files generated with
+@code{SELECT ... INTO OUTFILE} are readable to everyone, and you can't
+overwrite existing files.
+
+@tindex /etc/passwd
+The @strong{file} privilege may also be used to read any file accessible
+to the Unix user that the server runs as. This could be abused, for example,
+by using @code{LOAD DATA} to load @file{/etc/passwd} into a table, which
+can then be read with @code{SELECT}.
+
+@item
+If you don't trust your DNS, you should use IP numbers instead of hostnames
+in the grant tables. In principle, the @code{--secure} option to
+@code{mysqld} should make hostnames safe. In any case, you should be very
+careful about creating grant table entries using hostname values that
+contain wildcards!
+@end itemize
+
+The following @code{mysqld} options affect networking security:
+
+@table @code
+@item --secure
+IP numbers returned by the @code{gethostbyname()} system call are checked to
+make sure they resolve back to the original hostname. This makes it harder
+for someone on the outside to get access by pretending to be another host. This
+option also adds some sanity checks of hostnames. The option is turned off
+by default in @strong{MySQL} 3.21 because sometimes it takes a long time to
+perform backward resolutions. @strong{MySQL} 3.22 caches hostnames and has
+this option enabled by default.
+
+@item --skip-grant-tables
+This option causes the server not to use the privilege system at all. This
+gives everyone @emph{full access} to all databases! (You can tell a running
+server to start using the grant tables again by executing @code{mysqladmin
+flush-privileges} or @code{mysqladmin reload}.)
+
+@item --skip-name-resolve
+Hostnames are not resolved. All @code{Host} column values in the grant
+tables must be IP numbers or @code{localhost}.
+
+@item --skip-networking
+Don't allow TCP/IP connections over the network. All connections to
+@code{mysqld} must be made via Unix sockets. This option is unsuitable for
+systems that use MIT-pthreads, because the MIT-pthreads package doesn't
+support Unix sockets.
+@end table
+
+@node What Privileges, User names, Security, Privilege system
+@section What the privilege system does
+
+The primary function of the @strong{MySQL} privilege system is to
+authenticate a user connecting from a given host, and to associate that user
+with privileges on a database such as
+@strong{select}, @strong{insert}, @strong{update} and @strong{delete}.
+
+Additional functionality includes the ability to have an anonymous user and
+to grant privileges for @strong{MySQL}-specific functions such as @code{LOAD
+DATA INFILE} and administrative operations.
+
+@node User names, Connecting, What Privileges, Privilege system
+@section MySQL user names and passwords
+
+There are several distinctions between the way user names and passwords are
+used by @strong{MySQL}, and the way they are used by Unix or Windows:
+
+@itemize @bullet
+@item
+User names, as used by @strong{MySQL} for authentication purposes, have
+nothing to do with Unix user names (login names) or Windows user names. Most
+@strong{MySQL} clients by default try to log in using the current Unix user
+name as the @strong{MySQL} user name, but that is for convenience only.
+Client programs allow a different name to be specified with the @code{-u} or
+@code{--user} options. This means that you can't make a database secure in
+any way unless all @strong{MySQL} user names have passwords. Anyone may
+attempt to connect to the server using any name, and they will succeed if
+they specify any name that doesn't have a password.
+
+@item
+@strong{MySQL} user names can be up to 16 characters long; Unix user names
+typically are limited to 8 characters.
+
+@item
+@strong{MySQL} passwords have nothing to do with Unix passwords. There is no
+necessary connection between the password you use to log in to a Unix machine
+and the password you use to access a database on that machine.
+
+@item
+@strong{MySQL} encrypts passwords using a different algorithm than the one
+used during the Unix login process. See the descriptions of the
+@code{PASSWORD()} and @code{ENCRYPT()} functions in @ref{Miscellaneous
+functions}.
+@end itemize
+
+@node Connecting, Password security, User names, Privilege system
+@section Connecting to the MySQL server
+
+@strong{MySQL} client programs generally require that you specify connection
+parameters when you want to access a @strong{MySQL} server: the host you want
+to connect to, your user name and your password. For example, the
+@code{mysql} client can be started like this (optional arguments are enclosed
+between @samp{[} and @samp{]}):
+
+@example
+shell> mysql [-h host_name] [-u user_name] [-pyour_pass]
+@end example
+
+Alternate forms of the @code{-h}, @code{-u} and @code{-p} options are
+@code{--host=host_name}, @code{--user=user_name} and
+@code{--password=your_pass}. Note that there is @emph{no space} between
+@code{-p} or @code{--password=} and the password following it.
+
+@strong{NOTE:} Specifying a password on the command line is not secure!
+Any user on your system may then find out your password by typing a command
+like: @code{ps auxww}. @xref{Option files}.
+
+@code{mysql} uses default values for connection parameters that are missing
+from the command line:
+
+@itemize @bullet
+@item
+The default hostname is @code{localhost}.
+
+@item
+The default user name is your Unix login name.
+
+@item
+No password is supplied if @code{-p} is missing.
+@end itemize
+
+Thus, for a Unix user @code{joe}, the following commands are equivalent:
+
+@example
+shell> mysql -h localhost -u joe
+shell> mysql -h localhost
+shell> mysql -u joe
+shell> mysql
+@end example
+
+Other @strong{MySQL} clients behave similarly.
+
+On Unix systems, you can specify different default values to be used when you
+make a connection, so that you need not enter them on the command line each
+time you invoke a client program. This can be done in a couple of ways:
+
+@itemize @bullet
+@item
+@tindex .my.cnf file
+You can specify connection parameters in the @code{[client]} section of the
+@file{.my.cnf} configuration file in your home directory. The relevant
+section of the file might look like this:
+
+@example
+[client]
+host=host_name
+user=user_name
+password=your_pass
+@end example
+
+@xref{Option files}.
+
+@item
+@tindex MYSQL_HOST environment variable
+@tindex Environment variable, MYSQL_HOST
+@tindex MYSQL_PWD environment variable
+@tindex Environment variable, MYSQL_PWD
+@tindex USER environment variable
+@tindex Environment variable, USER
+You can specify connection parameters using environment variables. The
+host can be specified for @code{mysql} using @code{MYSQL_HOST}. The
+@strong{MySQL} user name can be specified using @code{USER} (this is for
+Windows only). The password can be specified using @code{MYSQL_PWD}
+(but this is insecure; see next section). @xref{Environment variables}.
+@end itemize
+
+@node Password security, Privileges provided, Connecting, Privilege system
+@section Keeping your password secure
+
+It is inadvisable to specify your password in a way that exposes it to
+discovery by other users. The methods you can use to specify your password
+when you run client programs are listed below, along with an assessment of
+the risks of each method:
+
+@itemize @bullet
+@item
+Use a @code{-pyour_pass} or @code{--password=your_pass} option on the command
+line. This is convenient but insecure, because your password becomes visible
+to system status programs (such as @code{ps}) that may be invoked by other
+users to display command lines. (@strong{MySQL} clients typically overwrite
+the command line argument with zeroes during their initialization sequence,
+but there is still a brief interval during which the value is visible.)
+
+@item
+Use a @code{-p} or @code{--password} option (with no @code{your_pass} value
+specified). In this case, the client program solicits the password from
+the terminal:
+
+@example
+shell> mysql -u user_name -p
+Enter password: ********
+@end example
+
+The client echoes @samp{*} characters to the terminal as you enter your
+password so that onlookers cannot see it.
+
+It is more secure to enter your password this way than to specify it on the
+command line because it is not visible to other users. However, this method
+of entering a password is suitable only for programs that you run
+interactively. If you want to invoke a client from a script that runs
+non-interactively, there is no opportunity to enter the password from the
+terminal. On some systems, you may even find that the first line of your
+script is read and interpreted (incorrectly) as your password!
+
+@item
+@tindex .my.cnf file
+Store your password in a configuration file. For example, you can list your
+password in the @code{[client]} section of the @file{.my.cnf} file in your
+home directory:
+
+@example
+[client]
+password=your_pass
+@end example
+
+If you store your password in @file{.my.cnf}, the file should not be group or
+world readable or writable. Make sure the file's access mode is @code{400}
+or @code{600}.
+
+@xref{Option files}.
+@item
+You can store your password in the @code{MYSQL_PWD} environment variable, but
+this method must be considered extremely insecure and should not be used.
+Some versions of @code{ps} include an option to display the environment of
+running processes; your password will be in plain sight for all to see if
+you set @code{MYSQL_PWD}. Even on systems without such a version of
+@code{ps}, it is unwise to assume there is no other method to observe process
+environments. @xref{Environment variables}.
+@end itemize
+
+All in all, the safest methods are to have the client program prompt for the
+password or to specify the password in a properly-protected @file{.my.cnf}
+file.
+
+@node Privileges provided, Privileges, Password security, Privilege system
+@section Privileges provided by MySQL
+
+Privilege information is stored in the @code{user}, @code{db}, @code{host},
+@code{tables_priv} and @code{columns_priv} tables in the @code{mysql}
+database (that is, in the database named @code{mysql}). The @strong{MySQL}
+server reads the contents of these tables when it starts up and under the
+circumstances indicated in @ref{Privilege changes}.
+
+The names used in this manual to refer to the privileges provided by
+@strong{MySQL} are shown below, along with the table column name associated
+with each privilege in the grant tables and the context in which the
+privilege applies:
+
+@multitable @columnfractions .15 .25 .6
+@item @strong{Privilege} @tab @strong{Column} @tab @strong{Context}
+@item @strong{select} @tab @code{Select_priv} @tab tables
+@item @strong{insert} @tab @code{Insert_priv} @tab tables
+@item @strong{update} @tab @code{Update_priv} @tab tables
+@item @strong{delete} @tab @code{Delete_priv} @tab tables
+@item @strong{index} @tab @code{Index_priv} @tab tables
+@item @strong{alter} @tab @code{Alter_priv} @tab tables
+@item @strong{create} @tab @code{Create_priv} @tab databases, tables or indexes
+@item @strong{drop} @tab @code{Drop_priv} @tab databases or tables
+@item @strong{grant} @tab @code{Grant_priv} @tab databases or tables
+@item @strong{references} @tab @code{References_priv} @tab databases or tables
+@item @strong{reload} @tab @code{Reload_priv} @tab server administration
+@item @strong{shutdown} @tab @code{Shutdown_priv} @tab server administration
+@item @strong{process} @tab @code{Process_priv} @tab server administration
+@item @strong{file} @tab @code{File_priv} @tab file access on server
+@end multitable
+
+The @strong{select}, @strong{insert}, @strong{update} and @strong{delete}
+privileges allow you to perform operations on rows in existing tables in
+a database.
+
+@code{SELECT} statements require the @strong{select} privilege only if they
+actually retrieve rows from a table. You can execute certain @code{SELECT}
+statements even without permission to access any of the databases on the
+server. For example, you could use the @code{mysql} client as a simple
+calculator:
+
+@example
+mysql> SELECT 1+1;
+mysql> SELECT PI()*2;
+@end example
+
+The @strong{index} privilege allows you to create or drop (remove) indexes.
+
+The @strong{alter} privilege allows you to use @code{ALTER TABLE}.
+
+The @strong{create} and @strong{drop} privileges allow you to create new
+databases and tables, or to drop (remove) existing databases and tables.
+
+Note that if you grant the @strong{drop} privilege for the @code{mysql}
+database to a user, that user can drop the database in which the
+@strong{MySQL} access privileges are stored!
+
+The @strong{grant} privilege allows you to give to other users those
+privileges you yourself possess.
+
+The @strong{file} privilege gives you permission to read and write files on
+the server using the @code{LOAD DATA INFILE} and @code{SELECT ... INTO
+OUTFILE} statements. Any user to whom this privilege is granted can read or
+write any file that the @strong{MySQL} server can read or write.
+
+The remaining privileges are used for administrative operations, which are
+performed using the @code{mysqladmin} program. The table below shows which
+@code{mysqladmin} commands each administrative privilege allows you to
+execute:
+
+@multitable @columnfractions .15 .85
+@item @strong{Privilege} @tab @strong{Commands permitted to privilege holders}
+@item @strong{reload} @tab @code{reload}, @code{refresh},
+@code{flush-privileges},
+@code{flush-hosts}, @code{flush-logs}, @code{flush-tables}
+@item @strong{shutdown} @tab @code{shutdown}
+@item @strong{process} @tab @code{processlist}, @code{kill}
+@end multitable
+
+The @code{reload} command tells the server to reread the grant tables. The
+@code{refresh} command flushes all tables and opens and closes the log
+files. @code{flush-privileges} is a synonym for @code{reload}. The other
+@code{flush-*} commands perform functions similar to @code{refresh} but are
+more limited in scope, and may be preferable in some instances. For example,
+if you want to flush just the log files, @code{flush-logs} is a better choice
+than @code{refresh}.
+
+The @code{shutdown} command shuts down the server.
+
+The @code{processlist} command displays information about the threads
+executing within the server. The @code{kill} command kills server threads.
+You can always display or kill your own threads, but you need the
+@strong{process} privilege to display or kill threads initiated by other
+users.
+
+It is a good idea in general to grant privileges only to those users who need
+them, but you should exercise particular caution in granting certain
+privileges:
+
+@itemize @bullet
+@item
+The @strong{grant} privilege allows users to give away their privileges to
+other users. Two users with different privileges and with the @strong{grant}
+privilege are able to combine privileges.
+
+@item
+The @strong{alter} privilege may be used to subvert the privilege system
+by renaming tables.
+
+@item
+The @strong{file} privilege can be abused to read any world-readable file on
+the server into a database table, the contents of which can then be
+accessed using @code{SELECT}. This includes the contents of all databases
+hosted by the server!
+
+@item
+The @strong{shutdown} privilege can be abused to deny service to other
+users entirely, by terminating the server.
+
+@item
+The @strong{process} privilege can be used to view the plain text of
+currently executing queries, including queries that set or change passwords.
+
+@item
+Privileges on the @code{mysql} database can be used to change passwords and
+other access privilege information. (Passwords are stored encrypted, so a
+malicious user cannot simply read them. However, with sufficient privileges,
+that same user can replace a password with a different one.)
+@end itemize
+
+There are some things that you cannot do with the @strong{MySQL}
+privilege system:
+
+@itemize @bullet
+@item
+You cannot explicitly specify that a given user should be denied access.
+That is, you cannot explicitly match a user and then refuse the connection.
+
+@item
+You cannot specify that a user has privileges to create or drop tables
+in a database but not to create or drop the database itself.
+@end itemize
+
+@node Privileges, Connection access, Privileges provided, Privilege system
+@section How the privilege system works
+
+The @strong{MySQL} privilege system ensures that all users may do exactly the
+things that they are supposed to be allowed to do. When you connect to a
+@strong{MySQL} server, your identity is determined by @strong{the host from
+which you connect} and @strong{the user name you specify}. The system grants
+privileges according to your identity and @strong{what you want to do}.
+
+@strong{MySQL} considers both your hostname and user name in identifying you
+because there is little reason to assume that a given user name belongs to
+the same person everywhere on the Internet. For example, the user
+@code{bill} who connects from @code{whitehouse.gov} need not be the same
+person as the user @code{bill} who connects from @code{microsoft.com}.
+@strong{MySQL} handles this by allowing you to distinguish users on different
+hosts that happen to have the same name: you can grant @code{bill} one set
+of privileges for connections from @code{whitehouse.gov}, and a different set
+of privileges for connections from @code{microsoft.com}.
+
+@strong{MySQL} access control involves two stages:
+
+@itemize @bullet
+@item
+Stage 1: The server checks whether or not you are even allowed to connect.
+
+@item
+Stage 2: Assuming you can connect, the server checks each request you issue
+to see whether or not you have sufficient privileges to perform it. For
+example, if you try to select rows from a table in a database or drop a table
+from the database, the server makes sure you have the @strong{select}
+privilege for the table or the @strong{drop} privilege for the database.
+@end itemize
+
+The server uses the @code{user}, @code{db} and @code{host} tables in the
+@code{mysql} database at both stages of access control. The fields in these
+grant tables are shown below:
+
+@multitable @columnfractions .2 .25 .25 .25
+@item @strong{Table name} @tab @code{user} @tab @code{db} @tab @code{host}
+
+@item @strong{Scope fields} @tab @code{Host} @tab @code{Host} @tab @code{Host}
+@item @tab @code{User} @tab @code{Db} @tab @code{Db}
+@item @tab @code{Password} @tab @code{User} @tab
+
+@item @strong{Privilege fields} @tab @code{Select_priv} @tab @code{Select_priv} @tab @code{Select_priv}
+@item @tab @code{Insert_priv} @tab @code{Insert_priv} @tab @code{Insert_priv}
+@item @tab @code{Update_priv} @tab @code{Update_priv} @tab @code{Update_priv}
+@item @tab @code{Delete_priv} @tab @code{Delete_priv} @tab @code{Delete_priv}
+@item @tab @code{Index_priv} @tab @code{Index_priv} @tab @code{Index_priv}
+@item @tab @code{Alter_priv} @tab @code{Alter_priv} @tab @code{Alter_priv}
+@item @tab @code{Create_priv} @tab @code{Create_priv} @tab @code{Create_priv}
+@item @tab @code{Drop_priv} @tab @code{Drop_priv} @tab @code{Drop_priv}
+@item @tab @code{Grant_priv} @tab @code{Grant_priv} @tab @code{Grant_priv}
+@item @tab @code{References_priv} @tab @tab
+@item @tab @code{Reload_priv} @tab @tab
+@item @tab @code{Shutdown_priv} @tab @tab
+@item @tab @code{Process_priv} @tab @tab
+@item @tab @code{File_priv} @tab @tab
+@end multitable
+
+For the second stage of access control (request verification), the server
+may, if the request involves tables, additionally consult the
+@code{tables_priv} and @code{columns_priv} tables. The fields in these
+tables are shown below:
+
+@multitable @columnfractions .2 .25 .25
+@item @strong{Table name} @tab @code{tables_priv} @tab @code{columns_priv}
+
+@item @strong{Scope fields} @tab @code{Host} @tab @code{Host}
+@item @tab @code{Db} @tab @code{Db}
+@item @tab @code{User} @tab @code{User}
+@item @tab @code{Table_name} @tab @code{Table_name}
+@item @tab @tab @code{Column_name}
+
+@item @strong{Privilege fields} @tab @code{Table_priv} @tab @code{Column_priv}
+@item @tab @code{Column_priv} @tab
+
+@item @strong{Other fields} @tab @code{Timestamp} @tab @code{Timestamp}
+@item @tab @code{Grantor} @tab
+@end multitable
+
+Each grant table contains scope fields and privilege fields.
+
+Scope fields determine the scope of each entry in the tables, i.e., the
+context in which the entry applies. For example, a @code{user} table entry
+with @code{Host} and @code{User} values of @code{'thomas.loc.gov'} and
+@code{'bob'} would be used for authenticating connections made to the server
+by @code{bob} from the host @code{thomas.loc.gov}. Similarly, a @code{db}
+table entry with @code{Host}, @code{User} and @code{Db} fields of
+@code{'thomas.loc.gov'}, @code{'bob'} and @code{'reports'} would be used when
+@code{bob} connects from the host @code{thomas.loc.gov} to access the
+@code{reports} database. The @code{tables_priv} and @code{columns_priv}
+tables contain scope fields indicating tables or table/column combinations
+to which each entry applies.
+
+@cindex Case sensitivity, in access checking
+For access-checking purposes, comparisons of @code{Host} values are
+case insensitive. @code{User}, @code{Password}, @code{Db} and
+@code{Table_name} values are case sensitive.
+@code{Column_name} values are case insensitive in @strong{MySQL} 3.22.12
+or later.
+
+Privilege fields indicate the privileges granted by a table entry, that is,
+what operations can be performed. The server combines the information in the
+various grant tables to form a complete description of a user's privileges.
+The rules used to do this are described in @ref{Request access}.
+
+Scope fields are strings, declared as shown below; the default value for
+each is the empty string:
+
+@multitable @columnfractions .15 .15 .7
+@item @strong{Field name} @tab @strong{Type}
+@item @code{Host} @tab @code{CHAR(60)}
+@item @code{User} @tab @code{CHAR(16)}
+@item @code{Password} @tab @code{CHAR(16)}
+@item @code{Db} @tab @code{CHAR(64)} @tab (@code{CHAR(60)} for the
+@code{tables_priv} and @code{columns_priv} tables)
+@item @code{Table_name} @tab @code{CHAR(60)}
+@item @code{Column_name} @tab @code{CHAR(60)}
+@end multitable
+
+In the @code{user}, @code{db} and @code{host} tables,
+all privilege fields are declared as @code{ENUM('N','Y')} --- each can have a
+value of @code{'N'} or @code{'Y'}, and the default value is @code{'N'}.
+
+In the @code{tables_priv} and @code{columns_priv} tables, the privilege
+fields are declared as @code{SET} fields:
+
+@multitable @columnfractions .2 .2 .6
+@item @strong{Table name} @tab @strong{Field name} @tab @strong{Possible set elements}
+@item @code{tables_priv} @tab @code{Table_priv} @tab @code{'Select', 'Insert',
+'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter'}
+@item @code{tables_priv} @tab @code{Column_priv} @tab @code{'Select', 'Insert',
+'Update', 'References'}
+@item @code{columns_priv} @tab @code{Column_priv} @tab @code{'Select', 'Insert',
+'Update', 'References'}
+@end multitable
+
+Briefly, the server uses the grant tables like this:
+
+@itemize @bullet
+@item
+The @code{user} table scope fields determine whether to allow or reject
+incoming connections. For allowed connections, any privileges granted in
+the @code{user} table indicate the user's global (superuser) privileges.
+These privileges apply to @strong{all} databases on the server.
+
+@item
+The @code{db} and @code{host} tables are used together:
+
+@itemize @minus
+@item
+The @code{db} table scope fields determine which users can access which
+databases from which hosts. The privilege fields determine which operations
+are allowed.
+
+@item
+The @code{host} table is used as an extension of the @code{db} table when you
+want a given @code{db} table entry to apply to several hosts. For example,
+if you want a user to be able to use a database from several hosts in
+your network, leave the @code{Host} value empty in the user's @code{db} table
+entry, then populate the @code{host} table with an entry for each of those
+hosts. This mechanism is described more detail in @ref{Request access}.
+@end itemize
+
+@item
+The @code{tables_priv} and @code{columns_priv} tables are similar to
+the @code{db} table, but are more fine-grained: they apply at the
+table and column level rather than at the database level.
+@end itemize
+
+Note that administrative privileges (@strong{reload}, @strong{shutdown},
+etc.) are specified only in the @code{user} table. This is because
+administrative operations are operations on the server itself and are not
+database-specific, so there is no reason to list such privileges in the
+other grant tables. In fact, only the @code{user} table need
+be consulted to determine whether or not you can perform an administrative
+operation.
+
+The @strong{file} privilege is specified only in the @code{user} table, too.
+It is not an administrative privilege as such, but your ability to read or
+write files on the server host is independent of the database you are
+accessing.
+
+The @code{mysqld} server reads the contents of the grant tables once, when it
+starts up. Changes to the grant tables take effect as indicated in
+@ref{Privilege changes}.
+
+When you modify the contents of the grant tables, it is a good idea to make
+sure that your changes set up privileges the way you want. For help in
+diagnosing problems, see @ref{Access denied}. For advice on security issues,
+@ref{Security}.
+
+A useful
+diagnostic tool is the @code{mysqlaccess} script, which Yves Carlier has
+provided for the @strong{MySQL} distribution. Invoke @code{mysqlaccess} with
+the @code{--help} option to find out how it works.
+Note that @code{mysqlaccess} checks access using only the @code{user},
+@code{db} and @code{host} tables. It does not check table- or column-level
+privileges.
+
+@node Connection access, Request access, Privileges, Privilege system
+@section Access control, stage 1: Connection verification
+
+When you attempt to connect to a @strong{MySQL} server, the server accepts or
+rejects the connection based on your identity and whether or not you can
+verify your identity by supplying the correct password. If not, the server
+denies access to you completely. Otherwise, the server accepts the
+connection, then enters stage 2 and waits for requests.
+
+Your identity is based on two pieces of information:
+
+@itemize @bullet
+@item
+The host from which you connect
+
+@item
+Your @strong{MySQL} user name
+@end itemize
+
+Identity checking is performed using the three @code{user} table scope fields
+(@code{Host}, @code{User} and @code{Password}). The server accepts the
+connection only if a @code{user} table entry matches your hostname and user
+name, and you supply the correct password.
+
+Values in the @code{user} table scope fields may be specified as follows:
+
+@itemize @bullet
+@item
+A @code{Host} value may be a hostname or an IP number, or @code{'localhost'}
+to indicate the local host.
+
+@item
+@cindex Wildcards, in @code{mysql.user} table
+You can use the wildcard characters @samp{%} and @samp{_} in the @code{Host}
+field.
+
+@item
+A @code{Host} value of @code{'%'} matches any hostname. A blank @code{Host}
+value is equivalent to @code{'%'}. Note that these values match @emph{any
+host that can create a connection to your server!}
+
+@cindex Netmask notation, in @code{mysql.user} table
+@item
+As of MySQL 3.23, for @code{Host} values specified as IP numbers, you
+can specify a netmask indicating how many address bits to use for the
+network number. For example:
+
+@example
+GRANT ALL PRIVILEGES on db.* to david@'192.58.197.0/255.255.255.0';
+@end example
+
+This will allow everyone to connect from an IP where the following is true:
+
+@example
+user_ip & netmask = host_ip.
+@end example
+
+In the above example all IP:s in the interval 192.58.197.0 -
+192.58.197.255 can connect to the @strong{MySQL} server.
+
+@item
+@cindex Anonymous user
+Wildcard characters are not allowed in the @code{User} field, but you can
+specify a blank value, which matches any name. If the @code{user} table
+entry that matches an incoming connection has a blank user name, the user is
+considered to be the anonymous user (the user with no name), rather than the
+name that the client actually specified. This means that a blank user name
+is used for all further access checking for the duration of the connection
+(that is, during stage 2).
+
+@item
+The @code{Password} field can be blank. This does not mean that any password
+matches, it means the user must connect without specifying a password.
+@end itemize
+
+@findex PASSWORD()
+Non-blank @code{Password} values represent encrypted passwords.
+@strong{MySQL} does not store passwords in plaintext form for anyone to see.
+Rather, the password supplied by a user who is attempting to connect is
+encrypted (using the @code{PASSWORD()} function) and compared to the
+already-encrypted version stored in the @code{user} table. If they match,
+the password is correct.
+
+The examples below show how various combinations of @code{Host} and
+@code{User} values in @code{user} table entries apply to incoming
+connections:
+
+@multitable @columnfractions .25 .15 .60
+@item @code{Host} @strong{value} @tab @code{User} @strong{value} @tab @strong{Connections matched by entry}
+@item @code{'thomas.loc.gov'} @tab @code{'fred'} @tab @code{fred}, connecting from @code{thomas.loc.gov}
+@item @code{'thomas.loc.gov'} @tab @code{''} @tab Any user, connecting from @code{thomas.loc.gov}
+@item @code{'%'} @tab @code{'fred'} @tab @code{fred}, connecting from any host
+@item @code{'%'} @tab @code{''} @tab Any user, connecting from any host
+@item @code{'%.loc.gov'} @tab @code{'fred'} @tab @code{fred}, connecting from any host in the @code{loc.gov} domain
+@item @code{'x.y.%'} @tab @code{'fred'} @tab @code{fred}, connecting from @code{x.y.net}, @code{x.y.com},@code{x.y.edu}, etc. (this is probably not useful)
+@item @code{'144.155.166.177'} @tab @code{'fred'} @tab @code{fred}, connecting from the host with IP address @code{144.155.166.177}
+@item @code{'144.155.166.%'} @tab @code{'fred'} @tab @code{fred}, connecting from any host in the @code{144.155.166} class C subnet
+@item @code{'144.155.166.0/24'} @tab @code{'fred'} @tab Same as previous example
+@end multitable
+
+Because you can use IP wildcard values in the @code{Host} field (e.g.,
+@code{'144.155.166.%'} to match every host on a subnet), there is the
+possibility that someone might try to exploit this capability by naming a
+host @code{144.155.166.somewhere.com}. To foil such attempts, @strong{MySQL}
+disallows matching on hostnames that start with digits and a dot. Thus, if
+you have a host named something like @code{1.2.foo.com}, its name will never
+match the @code{Host} column of the grant tables. Only an IP number can
+match an IP wildcard value.
+
+An incoming connection may be matched by more than one entry in the
+@code{user} table. For example, a connection from @code{thomas.loc.gov} by
+@code{fred} would be matched by several of the entries just shown above. How
+does the server choose which entry to use if more than one matches? The
+server resolves this question by sorting the @code{user} table after reading
+it at startup time, then looking through the entries in sorted order when a
+user attempts to connect. The first matching entry is the one that is used.
+
+@code{user} table sorting works as follows. Suppose the @code{user} table
+looks like this:
+
+@example
++-----------+----------+-
+| Host | User | ...
++-----------+----------+-
+| % | root | ...
+| % | jeffrey | ...
+| localhost | root | ...
+| localhost | | ...
++-----------+----------+-
+@end example
+
+When the server reads in the table, it orders the entries with the
+most-specific @code{Host} values first (@code{'%'} in the @code{Host} column
+means ``any host'' and is least specific). Entries with the same @code{Host}
+value are ordered with the most-specific @code{User} values first (a blank
+@code{User} value means ``any user'' and is least specific). The resulting
+sorted @code{user} table looks like this:
+
+@example
++-----------+----------+-
+| Host | User | ...
++-----------+----------+-
+| localhost | root | ...
+| localhost | | ...
+| % | jeffrey | ...
+| % | root | ...
++-----------+----------+-
+@end example
+
+@cindex Grant tables, sorting
+@cindex Sorting, grant tables
+@cindex @code{user} table, sorting
+When a connection is attempted, the server looks through the sorted entries
+and uses the first match found. For a connection from @code{localhost} by
+@code{jeffrey}, the entries with @code{'localhost'} in the @code{Host} column
+match first. Of those, the entry with the blank user name matches both the
+connecting hostname and user name. (The @code{'%'/'jeffrey'} entry would
+have matched, too, but it is not the first match in the table.)
+
+Here is another example. Suppose the @code{user} table looks like this:
+
+@example
++----------------+----------+-
+| Host | User | ...
++----------------+----------+-
+| % | jeffrey | ...
+| thomas.loc.gov | | ...
++----------------+----------+-
+@end example
+
+The sorted table looks like this:
+
+@example
++----------------+----------+-
+| Host | User | ...
++----------------+----------+-
+| thomas.loc.gov | | ...
+| % | jeffrey | ...
++----------------+----------+-
+@end example
+
+A connection from @code{thomas.loc.gov} by @code{jeffrey} is matched by the
+first entry, whereas a connection from @code{whitehouse.gov} by
+@code{jeffrey} is matched by the second.
+
+A common misconception is to think that for a given user name, all entries
+that explicitly name that user will be used first when the server attempts to
+find a match for the connection. This is simply not true. The previous
+example illustrates this, where a connection from @code{thomas.loc.gov} by
+@code{jeffrey} is first matched not by the entry containing @code{'jeffrey'}
+as the @code{User} field value, but by the entry with no user name!
+
+If you have problems connecting to the server, print out the @code{user}
+table and sort it by hand to see where the first match is being made.
+
+@node Request access, Privilege changes, Connection access, Privilege system
+@section Access control, stage 2: Request verification
+
+Once you establish a connection, the server enters stage 2. For each request
+that comes in on the connection, the server checks whether you have
+sufficient privileges to perform it, based on the type of operation you wish
+to perform. This is where the privilege fields in the grant tables come into
+play. These privileges can come from any of the @code{user}, @code{db},
+@code{host}, @code{tables_priv} or @code{columns_priv} tables. The grant
+tables are manipulated with @code{GRANT} and @code{REVOKE} commands.
+@xref{GRANT, , @code{GRANT}}. (You may find it helpful to refer to
+@ref{Privileges}, which lists the fields present in each of the grant
+tables.)
+
+The @code{user} table grants privileges that are assigned to you on a global
+basis and that apply no matter what the current database is. For example, if
+the @code{user} table grants you the @strong{delete} privilege, you can
+delete rows from any database on the server host! In other words,
+@code{user} table privileges are superuser privileges. It is wise to grant
+privileges in the @code{user} table only to superusers such as server or
+database administrators. For other users, you should leave the privileges
+in the @code{user} table set to @code{'N'} and grant privileges on a
+database-specific basis only, using the @code{db} and @code{host} tables.
+
+@cindex Anonymous user
+@cindex Wildcards, in @code{mysql.db} table
+@cindex Wildcards, in @code{mysql.host} table
+The @code{db} and @code{host} tables grant database-specific privileges.
+Values in the scope fields may be specified as follows:
+
+@itemize @bullet
+@item
+The
+wildcard characters @samp{%} and @samp{_} can be used in the @code{Host} and
+@code{Db} fields of either table.
+
+@item
+A @code{'%'} @code{Host} value in the @code{db} table means ``any host.'' A
+blank @code{Host} value in the @code{db} table means ``consult the
+@code{host} table for further information.''
+
+@item
+A @code{'%'} or blank @code{Host} value in the @code{host} table means ``any
+host.''
+
+@item
+A @code{'%'} or blank @code{Db} value in either table means ``any database.''
+
+@item
+A blank @code{User} value in either table matches the anonymous user.
+@end itemize
+
+@cindex Grant tables, sorting
+@cindex Sorting, grant tables
+@cindex @code{db} table, sorting
+@cindex @code{host} table, sorting
+The @code{db} and @code{host} tables are read in and sorted when the server
+starts up (at the same time that it reads the @code{user} table). The
+@code{db} table is sorted on the @code{Host}, @code{Db} and @code{User} scope
+fields, and the @code{host} table is sorted on the @code{Host} and @code{Db}
+scope fields. As with the @code{user} table, sorting puts the most-specific
+values first and least-specific values last, and when the server looks for
+matching entries, it uses the first match that it finds.
+
+
+@cindex Wildcards, in @code{mysql.tables_priv} table
+@cindex Wildcards, in @code{mysql.columns_priv} table
+The @code{tables_priv} and @code{columns_priv} tables grant table- and
+column-specific privileges. Values in the scope fields may be specified as
+follows:
+
+@itemize @bullet
+@item
+The wildcard characters @samp{%} and @samp{_}
+can be used in the @code{Host} field of either table.
+
+@item
+A @code{'%'} or blank @code{Host} value in either table means ``any host.''
+
+@item
+The @code{Db}, @code{Table_name} and @code{Column_name} fields cannot contain
+wildcards or be blank in either table.
+@end itemize
+
+The @code{tables_priv} and @code{columns_priv} tables are sorted on
+the @code{Host}, @code{Db} and @code{User} fields. This is similar to
+@code{db} table sorting, although the sorting is simpler because
+only the @code{Host} field may contain wildcards.
+
+The request verification process is described below. (If you are familiar
+with the access-checking source code, you will notice that the description
+here differs slightly from the algorithm used in the code. The description
+is equivalent to what the code actually does; it differs only to make the
+explanation simpler.)
+
+For administrative requests (@strong{shutdown}, @strong{reload}, etc.), the
+server checks only the @code{user} table entry, because that is the only table
+that specifies administrative privileges. Access is granted if the entry
+allows the requested operation and denied otherwise. For example, if you
+want to execute @code{mysqladmin shutdown} but your @code{user} table entry
+doesn't grant the @strong{shutdown} privilege to you, access is denied
+without even checking the @code{db} or @code{host} tables. (They
+contain no @code{Shutdown_priv} column, so there is no need to do so.)
+
+For database-related requests (@strong{insert}, @strong{update}, etc.), the
+server first checks the user's global (superuser) privileges by looking in
+the @code{user} table entry. If the entry allows the requested operation,
+access is granted. If the global privileges in the @code{user} table are
+insufficient, the server determines the user's database-specific privileges
+by checking the @code{db} and @code{host} tables:
+
+@enumerate
+@item
+The server looks in the @code{db} table for a match on the @code{Host},
+@code{Db} and @code{User} fields. The @code{Host} and @code{User} fields are
+matched to the connecting user's hostname and @strong{MySQL} user name. The
+@code{Db} field is matched to the database the user wants to access. If
+there is no entry for the @code{Host} and @code{User}, access is denied.
+
+@item
+If there is a matching @code{db} table entry and its @code{Host} field is
+not blank, that entry defines the user's database-specific privileges.
+
+@item
+If the matching @code{db} table entry's @code{Host} field is blank, it
+signifies that the @code{host} table enumerates which hosts should be allowed
+access to the database. In this case, a further lookup is done in the
+@code{host} table to find a match on the @code{Host} and @code{Db} fields.
+If no @code{host} table entry matches, access is denied. If there is a
+match, the user's database-specific privileges are computed as the
+intersection (@emph{not} the union!) of the privileges in the @code{db} and
+@code{host} table entries, i.e., the privileges that are @code{'Y'} in both
+entries. (This way you can grant general privileges in the @code{db} table
+entry and then selectively restrict them on a host-by-host basis using the
+@code{host} table entries.)
+@end enumerate
+
+After determining the database-specific privileges granted by the @code{db}
+and @code{host} table entries, the server adds them to the global privileges
+granted by the @code{user} table. If the result allows the requested
+operation, access is granted. Otherwise, the server checks the user's
+table and column privileges in the @code{tables_priv} and @code{columns_priv}
+tables and adds those to the user's privileges. Access is allowed or denied
+based on the result.
+
+Expressed in boolean terms, the preceding description of how a user's
+privileges are calculated may be summarized like this:
+
+@example
+global privileges
+OR (database privileges AND host privileges)
+OR table privileges
+OR column privileges
+@end example
+
+It may not be apparent why, if the global @code{user} entry privileges are
+initially found to be insufficient for the requested operation, the server
+adds those privileges to the database-, table- and column-specific privileges
+later. The reason is that a request might require more than one type of
+privilege. For example, if you execute an @code{INSERT ... SELECT}
+statement, you need both @strong{insert} and @strong{select} privileges.
+Your privileges might be such that the @code{user} table entry grants one
+privilege and the @code{db} table entry grants the other. In this case, you
+have the necessary privileges to perform the request, but the server cannot
+tell that from either table by itself; the privileges granted by the entries
+in both tables must be combined.
+
+The @code{host} table can be used to maintain a list of ``secure'' servers.
+At TcX, the @code{host} table contains a list of all machines on the local
+network. These are granted all privileges.
+
+You can also use the @code{host} table to indicate hosts that are @emph{not}
+secure. Suppose you have a machine @code{public.your.domain} that is located
+in a public area that you do not consider secure. You can allow access to
+all hosts on your network except that machine by using @code{host} table
+entries
+like this:
+
+@example
++--------------------+----+-
+| Host | Db | ...
++--------------------+----+-
+| public.your.domain | % | ... (all privileges set to 'N')
+| %.your.domain | % | ... (all privileges set to 'Y')
++--------------------+----+-
+@end example
+
+Naturally, you should always test your entries in the grant tables (e.g.,
+using @code{mysqlaccess}) to make sure your access privileges are actually
+set up the way you think they are.
+
+@node Privilege changes, Default privileges, Request access, Privilege system
+@section When privilege changes take effect
+
+When @code{mysqld} starts, all grant table contents are read into memory and
+become effective at that point.
+
+Modifications to the grant tables that you perform using @code{GRANT},
+@code{REVOKE}, or @code{SET PASSWORD} are noticed by the server immediately.
+
+If you modify the grant tables manually (using @code{INSERT}, @code{UPDATE},
+etc.), you should execute a @code{FLUSH PRIVILEGES} statement or run
+@code{mysqladmin flush-privileges} or @code{mysqladmin reload} to tell the
+server to reload the grant tables. Otherwise your changes will have @emph{no
+effect} until you restart the server. If you change the grant tables manually
+but forget to reload the privileges, you will be wondering why your changes
+don't seem to make any difference!
+
+When the server notices that the grant tables have been changed,
+existing client connections are affected as follows:
+
+@itemize @bullet
+@item
+Table and column privilege changes take effect with the client's next
+request.
+
+@item
+Database privilege changes take effect at the next @code{USE db_name}
+command.
+@end itemize
+
+Global privilege changes and password changes take effect the next time the
+client connects.
+
+@node Default privileges, Adding users, Privilege changes, Privilege system
+@section Setting up the initial MySQL privileges
+
+After installing @strong{MySQL}, you set up the initial access privileges by
+running @code{scripts/mysql_install_db}.
+@xref{Quick install}.
+The @code{mysql_install_db} script starts up the @code{mysqld}
+server, then initializes the grant tables to contain the following set
+of privileges:
+
+@itemize @bullet
+@item
+The @strong{MySQL} @code{root} user is created as a superuser who can do
+anything. Connections must be made from the local host.
+
+@strong{Note:}
+The initial @code{root} password is empty, so anyone can connect as @code{root}
+@emph{without a password} and be granted all privileges.
+
+@item
+@cindex Anonymous user
+An anonymous user is created that can do anything with databases that have a
+name of @code{'test'} or starting with @code{'test_'}. Connections must be
+made from the local host. This means any local user can connect without a
+password and be treated as the anonymous user.
+
+@item
+Other privileges are denied. For example, normal users can't use
+@code{mysqladmin shutdown} or @code{mysqladmin processlist}.
+@end itemize
+
+@strong{NOTE:} The default privileges are different for Win32.
+@xref{Win32 running}.
+
+Because your installation is initially wide open, one of the first things you
+should do is specify a password for the @strong{MySQL}
+@code{root} user. You can do this as follows (note that you specify the
+password using the @code{PASSWORD()} function):
+
+@example
+shell> mysql -u root mysql
+mysql> UPDATE user SET Password=PASSWORD('new_password')
+ WHERE user='root';
+mysql> FLUSH PRIVILEGES;
+@end example
+
+You can in @strong{MySQL} 3.22 and above use the @code{SET PASSWORD} statement:
+
+@example
+shell> mysql -u root mysql
+mysql> SET PASSWORD FOR root=PASSWORD('new_password');
+@end example
+
+Another way to set the password is by using the @code{mysqladmin} command:
+
+@example
+shell> mysqladmin -u root password new_password
+@end example
+
+Note that if you update the password in the @code{user} table directly using
+the first method, you must tell the server to reread the grant tables (with
+@code{FLUSH PRIVILEGES}), because the change will go unnoticed otherwise.
+
+Once the @code{root} password has been set, thereafter you must supply that
+password when you connect to the server as @code{root}.
+
+You may wish to leave the @code{root} password blank so that you don't need
+to specify it while you perform additional setup or testing. However, be sure
+to set it before using your installation for any real production work.
+
+See the @code{scripts/mysql_install_db} script to see how it sets up
+the default privileges. You can use this as a basis to see how to
+add other users.
+
+If you want the initial privileges to be different than those just described
+above, you can modify @code{mysql_install_db} before you run it.
+
+To recreate the grant tables completely, remove all the @file{*.frm},
+@file{*.MYI} and @file{*.MYD} files in the directory containing the
+@code{mysql} database. (This is the directory named @file{mysql} under
+the database directory, which is listed when you run @code{mysqld
+--help}.) Then run the @code{mysql_install_db} script, possibly after
+editing it first to have the privileges you want.
+
+@strong{NOTE:} For @strong{MySQL} versions older than 3.22.10, you should NOT
+delete the @file{*.frm} files. If you accidentally do this, you should
+copy them back from your @strong{MySQL} distribution before running
+@code{mysql_install_db}.
+
+@node Adding users, Passwords, Default privileges, Privilege system
+@section Adding new user privileges to MySQL
+
+You can add users two different ways: by using @code{GRANT} statements
+or by manipulating the @strong{MySQL} grant tables directly. The
+preferred method is to use @code{GRANT} statements, because they are
+more concise and less error-prone.
+
+The examples below show how to use the @code{mysql} client to set up new
+users. These examples assume that privileges are set up according to the
+defaults described in the previous section. This means that to make changes,
+you must be on the same machine where @code{mysqld} is running, you must
+connect as the @strong{MySQL} @code{root} user, and the @code{root} user must
+have the @strong{insert} privilege for the @code{mysql} database and the
+@strong{reload} administrative privilege. Also, if you have changed the
+@code{root} user password, you must specify it for the @code{mysql} commands
+below.
+
+You can add new users by issuing @code{GRANT} statements:
+
+@example
+shell> mysql --user=root mysql
+mysql> GRANT ALL PRIVILEGES ON *.* TO monty@@localhost
+ IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
+mysql> GRANT ALL PRIVILEGES ON *.* TO monty@@"%"
+ IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
+mysql> GRANT RELOAD,PROCESS ON *.* TO admin@@localhost;
+mysql> GRANT USAGE ON *.* TO dummy@@localhost;
+@end example
+
+These @code{GRANT} statements set up three new users:
+
+@table @code
+@item monty
+A full superuser who can connect to the server from anywhere, but who must
+use a password @code{'some_pass'} to do so. Note that we must issue
+@code{GRANT} statements for both @code{monty@@localhost} and
+@code{monty@@"%"}. If we don't add the entry with @code{localhost}, the
+anonymous user entry for @code{localhost} that is created by
+@code{mysql_install_db} will take precedence when we connect from the local
+host, because it has a more specific @code{Host} field value and thuse comes
+earlier in the @code{user} table sort order.
+
+@item admin
+A user who can connect from @code{localhost} without a password and who is
+granted the @strong{reload} and @strong{process} administrative privileges.
+This allows the user to execute the @code{mysqladmin reload},
+@code{mysqladmin refresh} and @code{mysqladmin flush-*} commands, as well as
+@code{mysqladmin processlist} . No database-related privileges are granted.
+(They can be granted later by issuing additional @code{GRANT} statements.)
+
+@item dummy
+A user who can connect without a password, but only from the local host. The
+global privileges are all set to @code{'N'} --- the @code{USAGE} privilege
+type allows you to create a user with no privileges. It is assumed that you
+will grant database-specific privileges later.
+@end table
+
+You can also add the same user access information directly by issuing
+@code{INSERT} statements and then telling the server to reload the grant
+tables:
+
+@example
+shell> mysql --user=root mysql
+mysql> INSERT INTO user VALUES('localhost','monty',PASSWORD('some_pass'),
+ 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y')
+mysql> INSERT INTO user VALUES('%','monty',PASSWORD('some_pass'),
+ 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y')
+mysql> INSERT INTO user SET Host='localhost',User='admin',
+ Reload_priv='Y', Process_priv='Y';
+mysql> INSERT INTO user (Host,User,Password)
+ VALUES('localhost','dummy','');
+mysql> FLUSH PRIVILEGES;
+@end example
+
+Depending on your @strong{MySQL} version, you may have to use a different
+number of @code{'Y'} values above (versions prior to 3.22.11 had fewer
+privilege columns). For the @code{admin} user, the more readable extended
+@code{INSERT} syntax that is available starting with 3.22.11 is used.
+
+Note that to set up a superuser, you need only create a @code{user} table
+entry with the privilege fields set to @code{'Y'}. No @code{db} or
+@code{host} table entries are necessary.
+
+The privilege columns in the @code{user} table were not set explicitly in the
+last @code{INSERT} statement (for the @code{dummy} user), so those columns
+are assigned the default value of @code{'N'}. This is the same thing that
+@code{GRANT USAGE} does.
+
+The following example adds a user @code{custom} who can connect from hosts
+@code{localhost}, @code{server.domain} and @code{whitehouse.gov}. He wants
+to access the @code{bankaccount} database only from @code{localhost},
+the @code{expenses} database only from @code{whitehouse.gov} and
+the @code{customer} database from all three hosts. He wants
+to use the password @code{stupid} from all three hosts.
+
+To set up this user's privileges using @code{GRANT} statements, run these
+commands:
+
+@example
+shell> mysql --user=root mysql
+mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
+ ON bankaccount.*
+ TO custom@@localhost
+ IDENTIFIED BY 'stupid';
+mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
+ ON expenses.*
+ TO custom@@whitehouse.gov
+ IDENTIFIED BY 'stupid';
+mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
+ ON customer.*
+ TO custom@@'%'
+ IDENTIFIED BY 'stupid';
+@end example
+
+To set up the user's privileges by modifying the grant tables directly,
+run these commands (note the @code{FLUSH PRIVILEGES} at the end):
+
+@example
+shell> mysql --user=root 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','bankaccount','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
+ ('whitehouse.gov','expenses','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('%','customer','custom','Y','Y','Y','Y','Y','Y');
+mysql> FLUSH PRIVILEGES;
+@end example
+
+The first three @code{INSERT} statements add @code{user} table entries that
+allow user @code{custom} to connect from the various hosts with the given
+password, but grant no permissions to him (all privileges are set to the
+default value of @code{'N'}). The next three @code{INSERT} statements add
+@code{db} table entries that grant privileges to @code{custom} for the
+@code{bankaccount}, @code{expenses} and @code{customer} databases, but only
+when accessed from the proper hosts. As usual, when the grant tables are
+modified directly, the server must be told to reload them (with
+@code{FLUSH PRIVILEGES}) so that the privilege changes take effect.
+
+If you want to give a specific user access from any machine in a given
+domain, you can issue a @code{GRANT} statement like the following:
+
+@example
+mysql> GRANT ...
+ ON *.*
+ TO myusername@@"%.mydomainname.com"
+ IDENTIFIED BY 'mypassword';
+@end example
+
+To do the same thing by modifying the grant tables directly, do this:
+
+@example
+mysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername',
+ PASSWORD('mypassword'),...);
+mysql> FLUSH PRIVILEGES;
+@end example
+
+You can also use @code{xmysqladmin}, @code{mysql_webadmin} and even
+@code{xmysql} to insert, change and update values in the grant tables.
+You can find these utilities in the
+@uref{http://www.mysql.com/Downloads/Contrib/,Contrib directory of the @strong{MySQL}
+Website}.
+
+@node Passwords, Access denied, Adding users, Privilege system
+@section How to set up passwords
+@cindex Passwords, setting
+@findex PASSWORD()
+
+The examples in the preceding sections illustrate an important principle:
+when you store a non-empty password using @code{INSERT} or @code{UPDATE}
+statements, you must use the @code{PASSWORD()} function to encrypt it. This
+is because the @code{user} table stores passwords in encrypted form, not as
+plaintext. If you forget that fact, you are likely to attempt to set
+passwords like this:
+
+@example
+shell> mysql -u root mysql
+mysql> INSERT INTO user (Host,User,Password)
+ VALUES('%','jeffrey','biscuit');
+mysql> FLUSH PRIVILEGES;
+@end example
+
+The result is that the plaintext value @code{'biscuit'} is stored as the
+password in the @code{user} table. When the user @code{jeffrey} attempts to
+connect to the server using this password, the @code{mysql} client encrypts
+it with @code{PASSWORD()} and sends the result to the server. The server
+compares the value in the @code{user} table (the encrypted value of
+@code{'biscuit'}) to the encrypted password (which is @emph{not}
+@code{'biscuit'}). The comparison fails and the server rejects the
+connection:
+
+@example
+shell> mysql -u jeffrey -pbiscuit test
+Access denied
+@end example
+
+Passwords must be encrypted when they are inserted in the @code{user}
+table, so the @code{INSERT} statement should have been specified like this
+instead:
+
+@example
+mysql> INSERT INTO user (Host,User,Password)
+ VALUES('%','jeffrey',PASSWORD('biscuit'));
+@end example
+
+You must also use the @code{PASSWORD()} function when you use @code{SET
+PASSWORD} statements:
+
+@example
+mysql> SET PASSWORD FOR jeffrey@@"%" = PASSWORD('biscuit');
+@end example
+
+If you set passwords using the @code{GRANT ... IDENTIFIED BY} statement
+or the @code{mysqladmin password} command, the @code{PASSWORD()} function
+is unnecessary. They both take care of encrypting the password for you,
+so you would specify a password of @code{'biscuit'} like this:
+
+@example
+mysql> GRANT USAGE ON *.* TO jeffrey@@"%" IDENTIFIED BY 'biscuit';
+@end example
+
+or
+
+@example
+shell> mysqladmin -u jeffrey password biscuit
+@end example
+
+@strong{NOTE:} @code{PASSWORD()} does not perform password encryption in the
+same way that Unix passwords are encrypted. You should not assume that if
+your Unix password and your @strong{MySQL} password are the same, that
+@code{PASSWORD()} will result in the same encrypted value as is stored in the
+Unix password file.
+@xref{User names}.
+
+@node Access denied, , Passwords, Privilege system
+@section Causes of @code{Access denied} errors
+
+If you encounter @code{Access denied} errors when you try to connect to the
+@strong{MySQL} server, the list below indicates some courses of
+action you can take to correct the problem:
+
+@itemize @bullet
+@item
+After installing @strong{MySQL}, did you run the @code{mysql_install_db} script
+to set up the initial grant table contents? If not, do
+so. @xref{Default privileges}. Test the initial privileges by
+executing this command:
+
+@example
+shell> mysql -u root test
+@end example
+
+The server should let you connect without error. You should also make sure
+you have a file @file{user.MYD} in the @strong{MySQL} database directory.
+Ordinarily, this is @file{PATH/var/mysql/user.MYD}, where @code{PATH} is the
+pathname to the @strong{MySQL} installation root.
+
+@item
+After a fresh installation, you should connect to the server and set up
+your users and their access permissions:
+
+@example
+shell> mysql -u root mysql
+@end example
+
+The server should let you connect because the @strong{MySQL} @code{root} user
+has no password initially. That is also a security risk, so setting the
+@code{root} password is something you should do while you're setting up
+your other @strong{MySQL} users.
+
+If you try to connect as @code{root} and get this error:
+
+@example
+Access denied for user: '@@unknown' to database mysql
+@end example
+
+this means that you don't have an entry in the @code{user} table with a
+@code{User} column value of @code{'root'} and that @code{mysqld} cannot
+resolve the hostname for your client. In this case, you must restart the
+server with the @code{--skip-grant-tables} option and edit your
+@file{/etc/hosts} or @file{\windows\hosts} file to add an entry for your
+host.
+
+@item
+@cindex @code{mysql_fix_privilege_tables}
+If you updated an existing @strong{MySQL} installation from a pre-3.22.11
+version to 3.22.11 or later, did you run the
+@code{mysql_fix_privilege_tables} script? If not, do so. The structure of
+the grant tables changed with @strong{MySQL} 3.22.11 when the @code{GRANT}
+statement became functional.
+
+@item
+If you make changes to the grant tables directly (using @code{INSERT} or
+@code{UPDATE} statement) and your changes seem to be ignored, remember that
+you must issue a @code{FLUSH PRIVILEGES} statement or execute a
+@code{mysqladmin flush-privileges} command to cause the server to reread the
+tables. Otherwise your changes have no effect until the next time the server
+is restarted. Remember that after you set the @code{root} password, you
+won't need to specify it until after you flush the privileges, because the
+server still won't know you've changed the password yet!
+
+@item
+If your privileges seem to have changed in the middle of a session, it may be
+that a superuser has changed them. Reloading the grant tables affects new
+client connections, but it also affects existing connections as indicated in
+@ref{Privilege changes}.
+
+@item
+For testing, start the @code{mysqld} daemon with the
+@code{--skip-grant-tables} option. Then you can change the @strong{MySQL}
+grant tables and use the @code{mysqlaccess} script to check whether or not
+your modifications have the desired effect. When you are satisfied with your
+changes, execute @code{mysqladmin flush-privileges} to tell the @code{mysqld}
+server to start using the new grant tables. @strong{Note:} Reloading the
+grant tables overrides the @code{--skip-grant-tables} option. This allows
+you to tell the server to begin using the grant tables again without bringing
+it down and restarting it.
+
+@item
+If you have access problems with a Perl, PHP, Python or ODBC program, try to
+connect to the server with @code{mysql -u user_name db_name} or @code{mysql
+-u user_name -pyour_pass db_name}. If you are able to connect using the
+@code{mysql} client, there is a problem with your program and not with the
+access privileges. (Notice that there is no space between @code{-p} and the
+password; you can also use the @code{--password=your_pass} syntax to specify
+the password.)
+
+@item
+If you can't get your password to work, remember that you must use
+the @code{PASSWORD()} function if you set the password with the
+@code{INSERT}, @code{UPDATE} or @code{SET PASSWORD} statements. The
+@code{PASSWORD()} function is unnecessary if you specify the password using
+the @code{GRANT ... INDENTIFIED BY} statement or the @code{mysqladmin
+password} command.
+@xref{Passwords}.
+
+@item
+@code{localhost} is a synonym for your local hostname, and is also the
+default host to which clients try to connect if you specify no host
+explicitly. However, connections to @code{localhost} do not work if you are
+running on a system that uses MIT-pthreads (@code{localhost} connections are
+made using Unix sockets, which are not supported by MIT-pthreads). To avoid
+this problem on such systems, you should use the @code{--host} option to name
+the server host explicitly. This will make a TCP/IP connection to the
+@code{mysqld} server. In this case, you must have your real hostname in
+@code{user} table entries on the server host. (This is true even if you are
+running a client program on the same host as the server.)
+
+@item
+If you get an @code{Access denied} error when trying to connect to the
+database with @code{mysql -u user_name db_name}, you may have a problem
+with the @code{user} table. Check this by executing @code{mysql -u root
+mysql} and issuing this SQL statement:
+
+@example
+mysql> SELECT * FROM user;
+@end example
+
+The result should include an entry with the @code{Host} and @code{User}
+columns matching your computer's hostname and your @strong{MySQL} user name.
+
+@item
+The @code{Access denied} error message will tell you who you are trying
+to log in as, the host from which you are trying to connect, and whether
+or not you were using a password. Normally, you should have one entry in
+the @code{user} table that exactly matches the hostname and user name
+that were given in the error message.
+
+@item
+If you get the following error when you try to connect from a different host
+than the one on which the @strong{MySQL} server is running, then there is no
+row in the @code{user} table that matches that host:
+
+@example
+Host ... is not allowed to connect to this MySQL server
+@end example
+
+You can fix this by using the command line tool @code{mysql} (on the
+server host!) to add a row to the @code{user}, @code{db} or @code{host}
+table for the user/hostname combination from which you are trying to
+connect and then execute @code{mysqladmin flush-privileges}. If you are
+not running @strong{MySQL} 3.22 and you don't know the IP number or
+hostname of the machine from which you are connecting, you should put an
+entry with @code{'%'} as the @code{Host} column value in the @code{user}
+table and restart @code{mysqld} with the @code{--log} option on the
+server machine. After trying to connect from the client machine, the
+information in the @strong{MySQL} log will indicate how you really did
+connect. (Then replace the @code{'%'} in the @code{user} table entry
+with the actual hostname that shows up in the log. Otherwise, you'll
+have a system that is insecure.)
+
+Another reason for this error on Linux is that you are using a binary
+@strong{MySQL} version that is compiled with a different glibc version
+than the one you are using. In this case you should either upgrade your
+OS/glibc or download the source @strong{MySQL} version and compile this
+yourself; A source RPM is normally trivial to compile and install, so
+normally this isn't a big problem.
+
+@item
+If @code{mysql -u root test} works but @code{mysql -h your_hostname -u root
+test} results in @code{Access denied}, then you may not have the correct name
+for your host in the @code{user} table. A common problem here is that the
+@code{Host} value in the user table entry specifies an unqualified hostname,
+but your system's name resolution routines return a fully-qualified domain
+name (or vice-versa). For example, if you have an entry with host
+@code{'tcx'} in the @code{user} table, but your DNS tells @strong{MySQL} that
+your hostname is @code{'tcx.subnet.se'}, the entry will not work. Try adding
+an entry to the @code{user} table that contains the IP number of your host as
+the @code{Host} column value. (Alternatively, you could add an entry to the
+@code{user} table with a @code{Host} value that contains a wildcard---for
+example, @code{'tcx.%'}. However, use of hostnames ending with @samp{%} is
+@emph{insecure} and is @emph{not} recommended!)
+
+@item
+If @code{mysql -u user_name test} works but @code{mysql -u user_name
+other_db_name} doesn't work, you don't have an entry for @code{other_db_name}
+listed in the @code{db} table.
+
+@item
+If @code{mysql -u user_name db_name} works when executed on the server
+machine, but @code{mysql -u host_name -u user_name db_name} doesn't work when
+executed on another client machine, you don't have the client machine listed
+in the @code{user} table or the @code{db} table.
+
+@item
+If you can't figure out why you get @code{Access denied}, remove from the
+@code{user} table all entries that have @code{Host} values containing
+wildcards (entries that contain @samp{%} or @samp{_}). A very common error
+is to insert a new entry with @code{Host}=@code{'%'} and
+@code{User}=@code{'some user'}, thinking that this will allow you to specify
+@code{localhost} to connect from the same machine. The reason that this
+doesn't work is that the default privileges include an entry with
+@code{Host}=@code{'localhost'} and @code{User}=@code{''}. Because that entry
+has a @code{Host} value @code{'localhost'} that is more specific than
+@code{'%'}, it is used in preference to the new entry when connecting from
+@code{localhost}! The correct procedure is to insert a second entry with
+@code{Host}=@code{'localhost'} and @code{User}=@code{'some_user'}, or to
+remove the entry with with @code{Host}=@code{'localhost'} and
+@code{User}=@code{''}.
+
+@item
+If you get the following error, you may have a problem with the @code{db} or
+@code{host} table:
+
+@example
+Access to database denied
+@end example
+
+If the entry selected from the @code{db} table has an empty value in the
+@code{Host} column, make sure there are one or more corresponding entries in
+the @code{host} table specifying which hosts the @code{db} table entry
+applies to.
+
+If you get the error when using the SQL commands @code{SELECT ...
+INTO OUTFILE} or @code{LOAD DATA INFILE}, your entry in the @code{user} table
+probably doesn't have the @strong{file} privilege enabled.
+
+@item
+@cindex Configuration files
+@cindex Environment variables
+@tindex .my.cnf file
+Remember that client programs will use connection parameters specified
+in configuration files or environment variables. @xref{Environment
+variables}. If a client seems to be sending the wrong default
+connection parameters when you don't specify them on the command line,
+check your environment and the @file{.my.cnf} file in your home
+directory. You might also check the system-wide @strong{MySQL}
+configuration files, though it is far less likely that client connection
+parameters will be specified there. @xref{Option files}. If you get
+@code{Access denied} when you run a client without any options, make
+sure you haven't specified an old password in any of your option files!
+@xref{Option files}.
+
+@item
+If everything else fails, start the @code{mysqld} daemon with a debugging
+option (for example, @code{--debug=d,general,query}). This will print host and
+user information about attempted connections, as well as information about
+each command issued. @xref{Debugging server}.
+
+@item
+If you have any other problems with the @strong{MySQL} grant tables and
+feel you must post the problem to the mailing list, always provide a
+dump of the @strong{MySQL} grant tables. You can dump the tables with
+the @code{mysqldump mysql} command. As always, post your problem using
+the @code{mysqlbug} script. @xref{Bug reports}. In some cases you may need
+to restart @code{mysqld} with @code{--skip-grant-tables} to be able to run
+@code{mysqldump}.
+@end itemize
+
+@node Reference, Table types, Privilege system, Top
+@chapter MySQL language reference
+
+@menu
+* Literals:: Literals: how to write strings and numbers
+* Variables:: User variables
+* Column types:: Column types
+* Functions:: Functions
+* CREATE DATABASE:: @code{CREATE DATABASE} syntax
+* DROP DATABASE:: @code{DROP DATABASE} syntax
+* CREATE TABLE:: @code{CREATE TABLE} syntax
+* ALTER TABLE:: @code{ALTER TABLE} syntax
+* DROP TABLE:: @code{DROP TABLE} syntax
+* OPTIMIZE TABLE:: @code{OPTIMIZE TABLE} syntax
+* CHECK TABLE:: @code{CHECK TABLE} syntax
+* ANALYZE TABLE::
+* REPAIR TABLE:: @code{REPAIR TABLE} syntax
+* DELETE:: @code{DELETE} syntax
+* SELECT:: @code{SELECT} syntax
+* JOIN:: @code{JOIN} syntax
+* INSERT:: @code{INSERT} syntax
+* REPLACE:: @code{REPLACE} syntax
+* LOAD DATA:: @code{LOAD DATA INFILE} syntax
+* UPDATE:: @code{UPDATE} syntax
+* USE:: @code{USE} syntax
+* FLUSH:: @code{Flush} syntax (clearing caches)
+* KILL:: @code{KILL} syntax
+* SHOW:: @code{SHOW} syntax (Get information about tables, columns, ...)
+* EXPLAIN:: @code{EXPLAIN} syntax (Get information about a @code{SELECT})
+* DESCRIBE:: @code{DESCRIBE} syntax (Get information about names of columns)
+* COMMIT:: @code{BEGIN/COMMIT/ROLLBACK} syntax
+* LOCK TABLES:: @code{LOCK TABLES/UNLOCK TABLES} syntax
+* SET OPTION:: @code{SET OPTION} syntax
+* GRANT:: @code{GRANT} and @code{REVOKE} syntax
+* CREATE INDEX:: @code{CREATE INDEX} syntax
+* DROP INDEX:: @code{DROP INDEX} syntax
+* Comments:: Comment syntax
+* CREATE FUNCTION:: @code{CREATE FUNCTION} syntax
+* Reserved words:: Is @strong{MySQL} picky about reserved words?
+@end menu
+
+
+@cindex Strings
+@cindex Strings, escaping characters
+@node Literals, Variables, Reference, Reference
+@section Literals: how to write strings and numbers
+
+@menu
+* String syntax:: Strings
+* Number syntax:: Numbers
+* Hexadecimal values:: Hexadecimal values
+* NULL values:: @code{NULL} values
+* Legal names:: Database, table, index, column and alias names
+@end menu
+
+@node String syntax, Number syntax, Literals, Literals
+@subsection Strings
+
+A string is a sequence of characters, surrounded by either single quote
+(@samp{'}) or double quote (@samp{"}) characters (only the single quote
+if you run in ANSI mode). Examples:
+
+@example
+'a string'
+"another string"
+@end example
+
+Within a string, certain sequences have special meaning. Each of these
+sequences begins with a backslash (@samp{\}), known as the @emph{escape
+character}. @strong{MySQL} recognizes the following escape sequences:
+
+@c these aren't really functions, but that's probably the most reasonable index
+@table @code
+@findex \0 (ASCII 0)
+@findex NUL
+@item \0
+An ASCII 0 (@code{NUL}) character.
+
+@findex \n (newline)
+@findex newline (\n)
+@item \n
+A newline character.
+
+@findex \t (tab)
+@findex tab (\t)
+@item \t
+A tab character.
+
+@findex \r (carriage return)
+@findex return (\r)
+@findex carriage return (\r)
+@item \r
+A carriage return character.
+
+@findex \b (backspace)
+@findex backspace (\b)
+@item \b
+A backspace character.
+
+@findex \' (single quote)
+@findex single quote (\')
+@item \'
+A single quote (@samp{'}) character.
+
+@findex \" (double quote)
+@findex double quote (\")
+@item \"
+A double quote (@samp{"}) character.
+
+@findex \\ (escape)
+@findex escape (\\)
+@item \\
+A backslash (@samp{\}) character.
+
+@findex % (wildcard character)
+@findex Wildcard character (%)
+@item \%
+A @samp{%} character. This is used to search for literal instances of
+@samp{%} in contexts where @samp{%} would otherwise be interpreted
+as a wildcard character. @xref{String comparison functions}.
+
+@findex _ (wildcard character)
+@findex Wildcard character (_)
+@item \_
+A @samp{_} character. This is used to search for literal instances of
+@samp{_} in contexts where @samp{_} would otherwise be interpreted
+as a wildcard character. @xref{String comparison functions}.
+@end table
+
+Note that if you use @samp{\%} or @samp{\_} in some string contexts, these
+will return the strings @samp{\%} and @samp{\_} and not @samp{%} and
+@samp{_}.
+
+@noindent
+There are several ways to include quotes within a string:
+
+@itemize @bullet
+@item
+A @samp{'} inside a string quoted with @samp{'} may be written as @samp{''}.
+
+@item
+A @samp{"} inside a string quoted with @samp{"} may be written as @samp{""}.
+
+@item
+You can precede the quote character with an escape character (@samp{\}).
+
+@item
+A @samp{'} inside a string quoted with @samp{"} needs no special treatment
+and need not be doubled or escaped. In the same way, @samp{"} inside a
+string quoted with @samp{'} needs no special treatment.
+@end itemize
+
+The @code{SELECT} statements shown below demonstrate how quoting and
+escaping work:
+
+@example
+mysql> SELECT 'hello', '"hello"', '""hello""', 'hel''lo', '\'hello';
++-------+---------+-----------+--------+--------+
+| hello | "hello" | ""hello"" | hel'lo | 'hello |
++-------+---------+-----------+--------+--------+
+
+mysql> SELECT "hello", "'hello'", "''hello''", "hel""lo", "\"hello";
++-------+---------+-----------+--------+--------+
+| hello | 'hello' | ''hello'' | hel"lo | "hello |
++-------+---------+-----------+--------+--------+
+
+mysql> SELECT "This\nIs\nFour\nlines";
++--------------------+
+| This
+Is
+Four
+lines |
++--------------------+
+@end example
+
+@cindex Quoting binary data
+
+If you want to insert binary data into a @code{BLOB} column, the following
+characters must be represented by escape sequences:
+@table @code
+@item NUL
+ASCII 0. You should represent this by @samp{\0} (a backslash and an ASCII @samp{0} character).
+@item \
+ASCII 92, backslash. Represent this by @samp{\\}.
+@item '
+ASCII 39, single quote. Represent this by @samp{\'}.
+@item "
+ASCII 34, double quote. Represent this by @samp{\"}.
+@end table
+
+@cindex Quoting
+@cindex @code{BLOB}, inserting binary data
+@findex mysql_escape_string()
+@findex DBI->quote
+If you write C code, you can use the C API function
+@code{mysql_escape_string()} to escape characters for the @code{INSERT}
+statement. @xref{C API function overview}. In Perl, you can use the
+@code{quote} method of the @code{DBI} package to convert special
+characters to the proper escape sequences. @xref{Perl DBI Class, , Perl
+@code{DBI} Class}.
+
+You should use an escape function on any string that might contain any of the
+special characters listed above!
+
+@node Number syntax, Hexadecimal values, String syntax, Literals
+@subsection Numbers
+
+Integers are represented as a sequence of digits. Floats use @samp{.} as a
+decimal separator. Either type of number may be preceded by @samp{-} to
+indicate a negative value.
+
+Examples of valid integers:
+
+@example
+1221
+0
+-32
+@end example
+
+Examples of valid floating-point numbers:
+
+@example
+294.42
+-32032.6809e+10
+148.00
+@end example
+
+An integer may be used in a floating-point context; it is interpreted
+as the equivalent floating-point number.
+
+@tindex Hexadecimal values
+@node Hexadecimal values, NULL values, Number syntax, Literals
+@subsection Hexadecimal values
+
+@strong{MySQL} supports hexadecimal values. In number context these acts
+like an integer (64 bit precision). In string context these acts like a binary
+string where each pair of hex digits is converted to a character.
+
+@example
+mysql> SELECT 0xa+0
+ -> 10
+mysql> select 0x5061756c;
+ -> Paul
+@end example
+
+Hexadecimal strings is often used by ODBC to give values for BLOB columns.
+
+@tindex NULL value
+@node NULL values, Legal names, Hexadecimal values, Literals
+@subsection @code{NULL} values
+
+The @code{NULL} value means ``no data'' and is different from values such
+as @code{0} for numeric types or the empty string for string types.
+@xref{Problems with NULL, , Problems with @code{NULL}}.
+
+@code{NULL} may be represented by @code{\N} when using the text file import
+or export formats (@code{LOAD DATA INFILE}, @code{SELECT ... INTO OUTFILE}).
+@xref{LOAD DATA, , @code{LOAD DATA}}.
+
+@node Legal names, , NULL values, Literals
+@subsection Database, table, index, column and alias names
+
+@menu
+* Name case sensitivity:: Case sensitivity in names
+@end menu
+
+Database, table, index, column and alias names all follow the same rules in
+@strong{MySQL}:
+
+@tindex Quoting of identifiers
+@tindex `
+@tindex "
+Note that the rules changed starting with @strong{MySQL} 3.23.6 when we
+introduced quoting of identifiers (database, table and column names)
+with @code{`} (@code{"} will also work to quote identifiers if you run
+in ANSI mode).
+
+@multitable @columnfractions .15 .7 .78
+@item @strong{Identifier} @tab @strong{max length} @tab @strong{Allowed characters}
+@item Database @tab 64 @tab Any character that is allowed in a directory name execpt @code{/}.
+@item Table @tab 64 @tab Any character that is allowed in file name, except @code{/} or @code{.}
+@item Column @tab 64 @tab All characters
+@item Alias @tab 255 @tab All characters
+@end multitable
+
+Note that in addition to the above, you can't have ASCII(0) or ASCII(255) in
+an identifier.
+
+Note that if the identifer is a restricted word or contains special character
+you must always quote it with @code{`} when you use it:
+
+@example
+SELECT * from `select` where `select`.id > 100;
+@end example
+
+In previous versions of @strong{MySQL}, the name rules are as follows:
+
+@itemize @bullet
+@item
+A name may consist of alphanumeric characters from the current character set
+and also @samp{_} and @samp{$}. The default character set is ISO-8859-1
+Latin1; this may be changed with the @code{--default-character-set} option
+to @code{mysqld}.
+@xref{Character sets}.
+
+@item
+A name may start with any character that is legal in a name. In particular,
+a name may start with a number (this differs from many other database
+systems!). However, a name cannot consist @emph{only} of numbers.
+
+@item
+You cannot use the @samp{.} character in names because it is used to extend the
+format by which you can refer to columns (see immediately below).
+@end itemize
+
+It is recommended that you do not use names like @code{1e}, because
+an expression like @code{1e+1} is ambiguous. It may be interpreted as the
+expression @code{1e + 1} or as the number @code{1e+1}.
+
+In @strong{MySQL} you can refer to a column using any of the following forms:
+
+@multitable @columnfractions .35 .65
+@item @strong{Column reference} @tab @strong{Meaning}
+@item @code{col_name} @tab Column @code{col_name}
+from whichever table used in the query contains a column of that name
+@item @code{tbl_name.col_name} @tab Column @code{col_name} from table
+@code{tbl_name} of the current database
+@item @code{db_name.tbl_name.col_name} @tab Column @code{col_name} from table
+@code{tbl_name} of the database @code{db_name}. This form is available in
+@strong{MySQL} 3.22 or later.
+@item
+@code{`column_name`} @tab A column that is a keyword or contains special characters.
+@end multitable
+
+You need not specify a @code{tbl_name} or @code{db_name.tbl_name} prefix for
+a column reference in a statement unless the reference would be ambiguous.
+For example, suppose tables @code{t1} and @code{t2} each contain a column
+@code{c}, and you retrieve @code{c} in a @code{SELECT} statement that uses
+both @code{t1} and @code{t2}. In this case, @code{c} is ambiguous because it
+is not unique among the tables used in the statement, so you must indicate
+which table you mean by writing @code{t1.c} or @code{t2.c}. Similarly, if
+you are retrieving from a table @code{t} in database @code{db1} and from a
+table @code{t} in database @code{db2}, you must refer to columns in those
+tables as @code{db1.t.col_name} and @code{db2.t.col_name}.
+
+@cindex ODBC compatibility
+@cindex Compatibility, with ODBC
+The syntax @code{.tbl_name} means the table @code{tbl_name} in the current
+database. This syntax is accepted for ODBC compatibility, because some ODBC
+programs prefix table names with a @samp{.} character.
+
+@node Name case sensitivity, , Legal names, Legal names
+@subsubsection Case sensitivity in names
+@cindex Database names, case sensitivity
+@cindex Table names, case sensitivity
+@cindex Column names, case sensitivity
+@cindex Alias names, case sensitivity
+@cindex Case sensitivity, of database names
+@cindex Case sensitivity, of table names
+@cindex Case sensitivity, of column names
+@cindex Case sensitivity, of alias names
+
+In @strong{MySQL}, databases and tables correspond to directories and files
+within those directories. Consequently, the case sensitivity of the
+underlying operating system determines the case sensitivity of database and
+table names. This means database and table names are case sensitive in Unix
+and case insensitive in Win32.
+
+@strong{Note:} Although database and table names are case insensitive for
+Win32, you should not refer to a given database or table using different
+cases within the same query. The following query would not work because it
+refers to a table both as @code{my_table} and as @code{MY_TABLE}:
+
+@example
+mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;
+@end example
+
+Column names are case insensitive in all cases.
+
+Aliases on tables are case sensitive. The following query would not work
+because it refers to the alias both as @code{a} and as @code{A}:
+
+@example
+mysql> SELECT col_name FROM tbl_name AS a
+ WHERE a.col_name = 1 OR A.col_name = 2;
+@end example
+
+Aliases on columns are case insensitive.
+
+@node Variables, Column types, Literals, Reference
+@section User variables
+
+@strong{MySQL} supports thread specific variables with the
+@code{@@variablename} syntax. A variable name may consist of
+alphanumeric characters from the current character set and also
+@samp{_}, @samp{$}, and @samp{.} . The default character set is
+ISO-8859-1 Latin1; this may be changed with the
+@code{--default-character-set} option to @code{mysqld}. @xref{Character
+sets}.
+
+Variables don't have to be initialized. They contain @code{NULL} by default
+and can store an integer, real or string value. All variables for
+a thread are automatically freed when the thread exits.
+
+You can set a variable with the @code{SET} syntax:
+
+@example
+SET @@variable= @{ integer expression | real expression | string expression @}
+[,@@variable= ...].
+@end example
+
+You can also set a variable in an expression with the @code{@@variable:=expr}
+syntax:
+
+@example
+select @@t1:=(@@t2:=1)+@@t3:=4,@@t1,@@t2,@@t3;
++----------------------+------+------+------+
+| @@t1:=(@@t2:=1)+@@t3:=4 | @@t1 | @@t2 | @@t3 |
++----------------------+------+------+------+
+| 5 | 5 | 1 | 4 |
++----------------------+------+------+------+
+@end example
+
+(We had to use the @code{:=} syntax here, because @code{=} was reserved for
+comparisons.)
+
+User variables may be used where expressions are allowed. Note that
+this does not currently include use in contexts where a number is explicitly
+required, such as in the @code{LIMIT} clause of a @code{SELECT} statement,
+or the @code{IGNORE number LINES} clause of a @code{LOAD DATA} statement.
+
+@strong{NOTE:} In a @code{SELECT} statement, each expression is only
+evaluated when it's sent to the client. This means that one can't
+in the @code{HAVING}, @code{GROUP BY} or @code{ORDER BY} clause refer to an
+expression that involves variables that are set in the @code{SELECT} part.
+For example, the following statement will NOT work as expected:
+
+@example
+SELECT (@@aa:=id) AS a, (@@aa+3) AS b FROM table_name HAVING b=5;
+@end example
+
+The reason is that @code{@@aa} will not contain the value of the current
+row, but the value of @code{id} for the previous accepted row.
+
+@node Column types, Functions, Variables, Reference
+@section Column types
+
+@strong{MySQL} supports a number of column types, which may be grouped into
+three categories: numeric types, date and time types, and string (character)
+types. This section first gives an overview of the types available and
+summarizes the storage requirements for each column type, then provides a
+more detailed description of the properties of the types in each category.
+The overview is intentionally brief. The more detailed descriptions should
+be consulted for additional information about particular column types, such
+as the allowable formats in which you can specify values.
+
+The column types supported by @strong{MySQL} are listed below.
+The following code letters are used in the descriptions:
+
+@table @code
+@item M
+Indicates the maximum display size. The maximum legal display size is 255.
+
+@item D
+Applies to floating-point types and indicates the number of digits
+following the decimal point. The maximum possible value is 30, but
+should be no greater than @code{M}-2.
+@end table
+
+Square brackets (@samp{[} and @samp{]}) indicate parts of type specifiers
+that are optional.
+
+@tindex Types
+
+@c The @w{-number} stuff keeps a linebreak from occurring between
+@c the - and number.
+
+Note that if you specify @code{ZEROFILL} for a column, @strong{MySQL} will
+automatically add the @code{UNSIGNED} attribute to the column.
+
+@table @code
+@tindex TINYINT
+@item TINYINT[(M)] [UNSIGNED] [ZEROFILL]
+
+A very small integer. The signed range is @code{-128} to @code{127}. The
+unsigned range is @code{0} to @code{255}.
+
+@tindex SMALLINT
+@item SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
+
+A small integer. The signed range is @code{-32768} to @code{32767}. The
+unsigned range is @code{0} to @code{65535}.
+
+@tindex MEDIUMINT
+@item MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
+
+A medium-size integer. The signed range is @code{-8388608} to
+@code{8388607}. The unsigned range is @code{0} to @code{16777215}.
+
+@tindex INT
+@item INT[(M)] [UNSIGNED] [ZEROFILL]
+
+A normal-size integer. The signed range is @code{-2147483648} to
+@code{2147483647}. The unsigned range is @code{0} to @code{4294967295}.
+
+@tindex INTEGER
+@item INTEGER[(M)] [UNSIGNED] [ZEROFILL]
+
+This is a synonym for @code{INT}.
+
+@tindex BIGINT
+@item BIGINT[(M)] [UNSIGNED] [ZEROFILL]
+
+A large integer. The signed range is @code{-9223372036854775808} to
+@code{9223372036854775807}. The unsigned range is @code{0} to
+@code{18446744073709551615}. Note that all arithmetic is done using
+signed @code{BIGINT} or @code{DOUBLE} values, so you shouldn't use
+unsigned big integers larger than @code{9223372036854775807} (63 bits)
+except with bit functions! Note that @code{-}, @code{+} and @code{*}
+will use @code{BIGINT} arithmetic when both arguments are @code{INTEGER}
+values! This means that if you multiply two big integers (or results
+from functions that return integers) you may get unexpected results if
+the result is larger than @code{9223372036854775807}.
+
+@tindex FLOAT
+@tindex FLOAT(precision)
+@item FLOAT(precision) [ZEROFILL]
+
+A floating-point number. Cannot be unsigned. @code{precision} can be
+@code{<=24} for a single precision floating point number and between 25
+and 53 for a double precision floating point number.
+these types are like the @code{FLOAT} and @code{DOUBLE} types described
+immediately below. @code{FLOAT(X)} have the same ranges as the
+corresponding @code{FLOAT} and @code{DOUBLE} types, but the display
+size and number of decimals is undefined.
+
+In @strong{MySQL} 3.23, this is a true floating point value. In
+earlier @strong{MySQL} versions, @code{FLOAT(precision)} always has 2 decimals.
+
+@cindex ODBC compatibility
+@cindex Compatibility, with ODBC
+This syntax is provided for ODBC compatibility.
+
+@tindex FLOAT
+@tindex FLOAT(M,D)
+@item FLOAT[(M,D)] [ZEROFILL]
+
+A small (single-precision) floating-point number. Cannot be unsigned.
+Allowable values are @code{@w{-3.402823466E+38}} to
+@code{@w{-1.175494351E-38}}, @code{0} and @code{@w{1.175494351E-38}} to
+@code{3.402823466E+38}. The M is the display width and D is the
+number of decimals. @code{FLOAT} without an argument or with an argument of
+<= 24 stands for a single-precision floating point number.
+
+@tindex DOUBLE
+@tindex FLOAT(precision)
+@item DOUBLE[(M,D)] [ZEROFILL]
+
+A normal-size (double-precision) floating-point number. Cannot be
+unsigned. Allowable values are @code{@w{-1.7976931348623157E+308}} to
+@code{@w{-2.2250738585072014E-308}}, @code{0} and
+@code{2.2250738585072014E-308} to @code{1.7976931348623157E+308}. The M
+is the display width and D is the number of decimals. @code{DOUBLE}
+without an argument or @code{FLOAT(X)} where 25 <= X <= 53 stands for a
+double-precision floating point number.
+
+@tindex DOUBLE PRECISION
+@tindex REAL
+@item DOUBLE PRECISION[(M,D)] [ZEROFILL]
+@itemx REAL[(M,D)] [ZEROFILL]
+
+These are synonyms for @code{DOUBLE}.
+
+@tindex DECIMAL
+@item DECIMAL[(M[,D])] [ZEROFILL]
+
+An unpacked floating-point number. Cannot be unsigned. Behaves like a
+@code{CHAR} column: ``unpacked'' means the number is stored as a string,
+using one character for each digit of the value. The decimal point,
+and, for negative numbers, the @samp{-} sign is not counted in M. If
+@code{D} is 0, values will have no decimal point or fractional part.
+The maximum range of @code{DECIMAL} values is the same as for
+@code{DOUBLE}, but the actual range for a given @code{DECIMAL} column
+may be constrained by the choice of @code{M} and @code{D}.
+
+If @code{D} is left out it's set to 0. If @code{M} is left out it's set to 10.
+
+Note that in @strong{MySQL} 3.22 the @code{M} argument includes the sign
+and the decimal point.
+
+@tindex NUMERIC
+@item NUMERIC(M,D) [ZEROFILL]
+
+This is a synonym for @code{DECIMAL}.
+
+@tindex DATE
+@item DATE
+
+A date. The supported range is @code{'1000-01-01'} to @code{'9999-12-31'}.
+@strong{MySQL} displays @code{DATE} values in @code{'YYYY-MM-DD'} format, but
+allows you to assign values to @code{DATE} columns using either strings or
+numbers.
+
+@tindex DATETIME
+@item DATETIME
+
+A date and time combination. The supported range is @code{'1000-01-01
+00:00:00'} to @code{'9999-12-31 23:59:59'}. @strong{MySQL} displays
+@code{DATETIME} values in @code{'YYYY-MM-DD HH:MM:SS'} format, but allows you
+to assign values to @code{DATETIME} columns using either strings or numbers.
+
+@tindex TIMESTAMP
+@item TIMESTAMP[(M)]
+
+A timestamp. The range is @code{'1970-01-01 00:00:00'} to sometime in the
+year @code{2037}. @strong{MySQL} displays @code{TIMESTAMP} values in
+@code{YYYYMMDDHHMMSS}, @code{YYMMDDHHMMSS}, @code{YYYYMMDD} or @code{YYMMDD}
+format, depending on whether @code{M} is @code{14} (or missing), @code{12},
+@code{8} or @code{6}, but allows you to assign values to @code{TIMESTAMP}
+columns using either strings or numbers. A @code{TIMESTAMP} column is useful
+for recording the date and time of an @code{INSERT} or @code{UPDATE}
+operation because it is automatically set to the date and time of the most
+recent operation if you don't give it a value yourself. You can also set it
+to the current date and time by assigning it a @code{NULL} value. @xref{Date
+and time types}.
+
+@tindex TIME
+@item TIME
+
+A time. The range is @code{'-838:59:59'} to @code{'838:59:59'}.
+@strong{MySQL} displays @code{TIME} values in @code{'HH:MM:SS'} format, but
+allows you to assign values to @code{TIME} columns using either strings or
+numbers.
+
+@tindex YEAR
+@item YEAR[(2|4)]
+
+A year in 2- or 4- digit formats (default is 4-digit). The allowable values are
+@code{1901} to @code{2155}, and @code{0000} in the 4 year format and
+1970-2069 if you use the 2 digit format (70-69). @strong{MySQL} displays
+@code{YEAR} values in @code{YYYY} format, but allows you to assign
+values to @code{YEAR} columns using either strings or numbers.
+(The @code{YEAR} type is new in @strong{MySQL} 3.22.)
+
+@tindex NATIONAL CHAR
+@tindex NCHAR
+@tindex CHAR
+@tindex CHARACTER
+@item [NATIONAL] CHAR(M) [BINARY]
+
+A fixed-length string that is always right-padded with spaces to the
+specified length when stored. The range of @code{M} is 1 to 255 characters.
+Trailing spaces are removed when the value is retrieved. @code{CHAR} values
+are sorted and compared in case-insensitive fashion according to the
+default character set unless the @code{BINARY} keyword is given.
+
+@code{NATIONAL CHAR} (short form @code{NCHAR}) is the ANSI SQL way to
+define that a CHAR column should use the default CHARACTER set. This is
+default in @code{MySQL}.
+
+@code{CHAR} is a shorthand for @code{CHARACTER}.
+
+@strong{MySQL} allows you to create a column of type
+@code{CHAR(0)}. This is mainly useful when you have to be compliant with
+some old applications that depend on the existence of a column but that do not
+actually use the value. This is also quite nice when you need a
+column that only can take 2 values: A @code{CHAR(0)}, that is not defined
+as @code{NOT NULL}, will only occupy one bit and can only take 2 values:
+@code{NULL} or @code{""}.
+
+@tindex CHARACTER VARYING
+@tindex CHAR VARYING
+@tindex VARCHAR
+@item [NATIONAL] VARCHAR(M) [BINARY]
+
+A variable-length string. Note:
+Trailing spaces are removed when the value is stored (this differs from the
+ANSI SQL specification). The range of @code{M} is 1 to 255 characters.
+@code{VARCHAR} values are sorted and compared in case-insensitive fashion
+unless the @code{BINARY} keyword is given. @xref{Silent column changes}.
+
+@code{VARCHAR} is a shorthand for @code{CHARACTER VARYING}.
+
+@tindex TINYBLOB
+@tindex TINYTEXT
+@item TINYBLOB
+@itemx TINYTEXT
+
+A @code{BLOB} or @code{TEXT} column with a maximum length of 255 (2^8 - 1)
+characters. @xref{Silent column changes}.
+
+@tindex BLOB
+@tindex TEXT
+@item BLOB
+@itemx TEXT
+
+A @code{BLOB} or @code{TEXT} column with a maximum length of 65535 (2^16 - 1)
+characters. @xref{Silent column changes}.
+
+@tindex MEDIUMBLOB
+@tindex MEDIUMTEXT
+@item MEDIUMBLOB
+@itemx MEDIUMTEXT
+
+A @code{BLOB} or @code{TEXT} column with a maximum length of 16777215
+(2^24 - 1) characters. @xref{Silent column changes}.
+
+@tindex LONGBLOB
+@tindex LONGTEXT
+@item LONGBLOB
+@itemx LONGTEXT
+
+A @code{BLOB} or @code{TEXT} column with a maximum length of 4294967295
+(2^32 - 1) characters. @xref{Silent column changes}.
+
+@tindex ENUM
+@item ENUM('value1','value2',...)
+
+An enumeration.
+A string object that can have only one value, chosen from the list of values
+@code{'value1'}, @code{'value2'}, @code{...}, or @code{NULL}. An @code{ENUM}
+can have a maximum of 65535 distinct values.
+
+@tindex SET
+@item SET('value1','value2',...)
+
+A set. A string object that can have zero or more values, each of which must
+be chosen from the list of values @code{'value1'}, @code{'value2'},
+@code{...} A @code{SET} can have a maximum of 64 members.
+@end table
+
+@menu
+* Storage requirements:: Column type storage requirements
+* Numeric types:: Numeric types
+* Date and time types:: Date and time types
+* String types:: String types
+* Choosing types:: Choosing the right type for a column
+* Indexes:: Column indexes
+* Multiple-column indexes:: Multiple-column indexes
+* Other-vendor column types:: Using column types from other database engines
+@end menu
+
+@cindex Storage requirements
+@node Storage requirements, Numeric types, Column types, Column types
+@subsection Column type storage requirements
+
+The storage requirements for each of the column types supported by
+@strong{MySQL} are listed below by category.
+
+@subheading Numeric types
+
+@multitable @columnfractions .35 .65
+@item @strong{Column type} @tab @strong{Storage required}
+@item @code{TINYINT} @tab 1 byte
+@item @code{SMALLINT} @tab 2 bytes
+@item @code{MEDIUMINT} @tab 3 bytes
+@item @code{INT} @tab 4 bytes
+@item @code{INTEGER} @tab 4 bytes
+@item @code{BIGINT} @tab 8 bytes
+@item @code{FLOAT(X)} @tab 4 if X <= 24 or 8 if 25 <= X <= 53
+@item @code{FLOAT} @tab 4 bytes
+@item @code{DOUBLE} @tab 8 bytes
+@item @code{DOUBLE PRECISION} @tab 8 bytes
+@item @code{REAL} @tab 8 bytes
+@item @code{DECIMAL(M,D)} @tab @code{M} bytes (@code{D}+2, if @code{M < D})
+@item @code{NUMERIC(M,D)} @tab @code{M} bytes (@code{D}+2, if @code{M < D})
+@end multitable
+
+@subheading Date and time types
+
+@multitable @columnfractions .35 .65
+@item @strong{Column type} @tab @strong{Storage required}
+@item @code{DATE} @tab 3 bytes
+@item @code{DATETIME} @tab 8 bytes
+@item @code{TIMESTAMP} @tab 4 bytes
+@item @code{TIME} @tab 3 bytes
+@item @code{YEAR} @tab 1 byte
+@end multitable
+
+@subheading String types
+
+@multitable @columnfractions .35 .65
+@item @strong{Column type} @tab @strong{Storage required}
+@item @code{CHAR(M)} @tab @code{M} bytes, @code{1 <= M <= 255}
+@item @code{VARCHAR(M)} @tab @code{L}+1 bytes, where @code{L <= M} and
+@code{1 <= M <= 255}
+@item @code{TINYBLOB}, @code{TINYTEXT} @tab @code{L}+1 bytes,
+where @code{L} < 2^8
+@item @code{BLOB}, @code{TEXT} @tab @code{L}+2 bytes,
+where @code{L} < 2^16
+@item @code{MEDIUMBLOB}, @code{MEDIUMTEXT} @tab @code{L}+3 bytes,
+where @code{L} < 2^24
+@item @code{LONGBLOB}, @code{LONGTEXT} @tab @code{L}+4 bytes,
+where @code{L} < 2^32
+@item @code{ENUM('value1','value2',...)} @tab 1 or 2 bytes, depending on
+the number of enumeration values (65535 values maximum)
+@item @code{SET('value1','value2',...)} @tab 1, 2, 3, 4 or 8 bytes, depending
+on the number of set members (64 members maximum)
+@end multitable
+
+@code{VARCHAR} and the @code{BLOB} and @code{TEXT} types are variable-length
+types, for which the storage requirements depend on the actual length of
+column values (represented by @code{L} in the preceding table), rather than
+on the type's maximum possible size. For example, a @code{VARCHAR(10)}
+column can hold a string with a maximum length of 10 characters. The actual
+storage required is the length of the string (@code{L}), plus 1 byte to
+record the length of the string. For the string @code{'abcd'}, @code{L} is 4
+and the storage requirement is 5 bytes.
+
+The @code{BLOB} and @code{TEXT} types require 1, 2, 3 or 4 bytes to record
+the length of the column value, depending on the maximum possible length of
+the type.
+
+If a table includes any variable-length column types, the record format will
+also be variable-length. Note that when a table is created, @strong{MySQL}
+may under certain conditions change a column from a variable-length type to a
+fixed-length type, or vice-versa. @xref{Silent column changes}.
+
+The size of an @code{ENUM} object is determined by the number of different
+enumeration values. 1 byte is used for enumerations with up to 255 possible
+values. 2 bytes are used for enumerations with up to 65535 values.
+
+The size of a @code{SET} object is determined by the number of different
+set members. If the set size is @code{N}, the object occupies @code{(N+7)/8}
+bytes, rounded up to 1, 2, 3, 4 or 8 bytes. A @code{SET} can have a maximum
+of 64 members.
+
+@node Numeric types, Date and time types, Storage requirements, Column types
+@subsection Numeric types
+
+@strong{MySQL} supports all of the ANSI/ISO SQL92 numeric types. These
+types include the exact numeric data types (@code{NUMERIC},
+@code{DECIMAL}, @code{INTEGER}, and @code{SMALLINT}), as well as the
+approximate numeric data types (@code{FLOAT}, @code{REAL}, and
+@code{DOUBLE PRECISION}). The keyword @code{INT} is a synonym for
+@code{INTEGER}, and the keyword @code{DEC} is a synonym for
+@code{DECIMAL}.
+
+The @code{NUMERIC} and @code{DECIMAL} types are implemented as the same
+type by @strong{MySQL}, as permitted by the SQL92 standard. They are
+used for values for which it is important to preserve exact precision,
+for example with monetary data. When declaring a column of one of these
+types the precision and scale can be (and usually is) specified; for
+example:
+
+@example
+ salary DECIMAL(9,2)
+@end example
+
+In this example, @code{9} (@code{precision}) represents the number of
+significant decimal digits which will be stored for values, and
+@code{2} (@code{scale}) represents the number of digits which will be
+stored following the decimal point. In this case, therefore, the range
+of values which can be stored in the @code{salary} column is from
+@code{-9999999.99} to @code{9999999.99}. In ANSI/ISO SQL92, the syntax
+@code{DECIMAL(p)} is equivalent to @code{DECIMAL(p,0)}. Similarly, the
+syntax @code{DECIMAL} is equivalent to @code{DECIMAL(p,0)}, where the
+implementation is allowed to decide the value of @code{p}.
+@strong{MySQL} does not currently support either of these variant forms
+of the @code{DECIMAL}/@code{NUMERIC} data types. This is not generally
+a serious problem, as the principal benefits of these types derive from
+the ability to control both precision and scale explicitly.
+
+@code{DECIMAL} and @code{NUMERIC} values are stored as strings, rather
+than as binary floating point numbers, in order to preserve the decimal
+precision of those values. One character is used for each digit of the
+value, the decimal point (if @code{scale} > 0) and the @samp{-} sign
+(for negative numbers). If @code{scale} is 0, @code{DECIMAL} and
+@code{NUMERIC} values contain no decimal point or fractional part.
+
+The maximum range of @code{DECIMAL} and @code{NUMERIC} values is the
+same as for @code{DOUBLE}, but the actual range for a given
+@code{DECIMAL} or @code{NUMERIC} column can be constrained by the
+@code{precision} or @code{scale} for a given column. When such a column
+is assigned a value with more digits following the decimal point than
+are allowed by the specified @code{scale}, the value is rounded to that
+@code{scale}. When a @code{DECIMAL} or @code{NUMERIC} column is
+assigned a value whose magnitude exceeds the range implied by the
+specified (or defaulted) @code{precision} and @code{scale},
+@strong{MySQL} stores the value representing the corresponding end
+point of that range.
+
+As an extension to the ANSI/ISO SQL92 standard, @strong{MySQL} also
+supports the integral types @code{TINYINT}, @code{MEDIUMINT}, and
+@code{BIGINT} as listed in the tables above. Another extension is
+supported by @strong{MySQL} for optionally specifying the display width
+of an integral value in parentheses following the base keyword for the
+type (for example, @code{INT(4)}). This optional width specification is
+used to left-pad the display of values whose width is less than the
+width specified for the column, but does not constrain the range of
+values which can be stored in the column, nor the number of digits which
+will be displayed for values whose width exceeds that specified for the
+column. When used in conjunction with the optional extension attribute
+@code{ZEROFILL} the default padding of spaces is replaced with zeroes.
+For example, for a column declared as @code{INT(5) ZEROFILL}, a value
+of @code{4} is retrieved as @code{00004}. Note that if you store larger
+values than the display width in an integral column, you may experience
+problems when @strong{MySQL} generates temporary tables for some
+complicated joins as in these case @strong{MySQL} trust that the data
+did fit into the original column width.
+
+All integral types can have an optional (non-standard) attribute
+@code{UNSIGNED}. Unsigned values can be used when you want to allow
+only positive numbers in a column and you need a little bigger numeric
+range for the column.
+
+The @code{FLOAT} type is used to represent approximate numeric data
+types. The ANSI/ISO SQL92 standard allows an optional specification of
+the precision (but not the range of the exponent) in bits following the
+keyword @code{FLOAT} in parentheses. The @strong{MySQL} implementation
+also supports this optional precision specification. When the keyword
+@code{FLOAT} is used for a column type without a precision
+specification, @strong{MySQL} uses four bytes to store the values. A
+variant syntax is also supported, with two numbers given in parentheses
+following the @code{FLOAT} keyword. With this option, the first number
+continues to represent the storage requirements for the value in bytes,
+and the second number specifies the number of digits to be stored and
+displayed following the decimal point (as with @code{DECIMAL} and
+@code{NUMERIC}). When @strong{MySQL} is asked to store a number for
+such a column with more decimal digits following the decimal point than
+specified for the column, the value is rounded to eliminate the extra
+digits when the value is stored.
+
+The @code{REAL} and @code{DOUBLE PRECISION} types do not accept
+precision specifications. As an extension to the ANSI/ISO SQL92
+standard, @strong{MySQL} recognizes @code{DOUBLE} as a synonym for the
+@code{DOUBLE PRECISION} type. In contrast with the standard's
+requirement that the precision for @code{REAL} be smaller than that used
+for @code{DOUBLE PRECISION}, @strong{MySQL} implements both as 8-byte
+double-precision floating point values (when running in non-"Ansi mode").
+For maximum portability, code requiring storage of approximate numeric
+data values should use @code{FLOAT} or @code{DOUBLE PRECISION} with no
+specification of precision or number of decimal points.
+
+When asked to store a value in a numeric column that is outside the column
+type's allowable range, @strong{MySQL} clips the value to the appropriate
+endpoint of the range and stores the resulting value instead.
+
+For example, the range of an @code{INT} column is @code{-2147483648} to
+@code{2147483647}. If you try to insert @code{-9999999999} into an
+@code{INT} column, the value is clipped to the lower endpoint of the range,
+and @code{-2147483648} is stored instead. Similarly, if you try to insert
+@code{9999999999}, @code{2147483647} is stored instead.
+
+If the @code{INT} column is @code{UNSIGNED}, the size of the column's
+range is the same but its endpoints shift up to @code{0} and @code{4294967295}.
+If you try to store @code{-9999999999} and @code{9999999999},
+the values stored in the column become @code{0} and @code{4294967296}.
+
+Conversions that occur due to clipping are reported as ``warnings'' for
+@code{ALTER TABLE}, @code{LOAD DATA INFILE}, @code{UPDATE} and
+multi-row @code{INSERT} statements.
+
+@cindex Types, Date and Time
+@cindex Date and Time types
+@node Date and time types, String types, Numeric types, Column types
+@subsection Date and time types
+
+@menu
+* Y2K issues:: Y2K issues and date types
+* DATETIME:: The @code{DATETIME}, @code{DATE} and @code{TIMESTAMP} types
+* TIME:: The @code{TIME} type
+* YEAR:: The @code{YEAR} type
+@end menu
+
+The date and time types are @code{DATETIME}, @code{DATE},
+@code{TIMESTAMP}, @code{TIME} and @code{YEAR}. Each of these has a
+range of legal values, as well as a ``zero'' value that is used when you
+specify a really illegal value. Note that @strong{MySQL} allows you to store
+certain 'not strictly' legal date values, for example @code{1999-11-31}.
+The reason for this is that we think it's the responsibility of the
+application to handle date checking, not the SQL servers. To make the
+date checking 'fast', @strong{MySQL} only checks that the month is in
+the range of 0-12 and the day is in the range of 0-31. The above ranges
+are defined this way because @strong{MySQL} allows you to store, in a
+@code{DATE} or @code{DATETIME} column, dates where the day or month-day
+are zero. This is extremely useful for applications that need to store
+a birth-date for which you don't know the exact date. In this case you
+simply store the date like @code{1999-00-00} or @code{1999-01-00}. (You
+can of course not expect to get a correct value from functions like
+@code{DATE_SUB()} or @code{DATE_ADD} for dates like these).
+
+Here are some general considerations to keep in mind when working
+with date and time types:
+
+@itemize @bullet
+@item
+@strong{MySQL} retrieves values for a given date or time type in a standard
+format, but it attempts to interpret a variety of formats for values that
+you supply (e.g., when you specify a value to be assigned to or compared to a
+date or time type). Nevertheless, only the formats described in the
+following sections are supported. It is expected that you will supply legal
+values, and unpredictable results may occur if you use values in other
+formats.
+
+@item
+Although @strong{MySQL} tries to interpret values in several formats, it
+always expects the year part of date values to be leftmost. Dates must be
+given in year-month-day order (e.g., @code{'98-09-04'}), rather than in the
+month-day-year or day-month-year orders commonly used elsewhere (e.g.,
+@code{'09-04-98'}, @code{'04-09-98'}).
+
+@item
+@strong{MySQL} automatically converts a date or time type value to a number
+if the value is used in a numeric context, and vice versa.
+
+@item
+When @strong{MySQL} encounters a value for a date or time type that is
+out of range or otherwise illegal for the type (see start of this
+section), it converts the value to the ``zero'' value for that type.
+(The exception is that out-of-range @code{TIME} values are clipped to
+the appropriate endpoint of the @code{TIME} range.) The table below
+shows the format of the ``zero'' value for each type:
+
+@multitable @columnfractions .3 .7
+@item @strong{Column type} @tab @strong{``Zero'' value}
+@item @code{DATETIME} @tab @code{'0000-00-00 00:00:00'}
+@item @code{DATE} @tab @code{'0000-00-00'}
+@item @code{TIMESTAMP} @tab @code{00000000000000} (length depends on display size)
+@item @code{TIME} @tab @code{'00:00:00'}
+@item @code{YEAR} @tab @code{0000}
+@end multitable
+
+@item
+The ``zero'' values are special, but you can store or refer to them
+explicitly using the values shown in the table. You can also do this
+using the values @code{'0'} or @code{0}, which are easier to write.
+
+@item
+``Zero'' date or time values used through @strong{MyODBC} are converted
+automatically to @code{NULL} in @strong{MyODBC} 2.50.12 and above, because
+ODBC can't handle such values.
+@end itemize
+
+@cindex Year 2000 issues
+@node Y2K issues, DATETIME, Date and time types, Date and time types
+@subsubsection Y2K issues and date types
+
+@strong{MySQL} itself is Y2K-safe (@pxref{Year 2000 compliance}),
+but input values presented to @strong{MySQL} may not be. Any input
+containing 2-digit year values is ambiguous, because the century is unknown.
+Such values must be interpreted into 4-digit form because @strong{MySQL} stores
+years internally using four digits.
+
+For @code{DATETIME}, @code{DATE}, @code{TIMESTAMP} and @code{YEAR} types,
+@strong{MySQL} interprets dates with ambiguous year values using the
+following rules:
+
+@itemize @bullet
+@item
+Year values in the range @code{00-69} are converted to @code{2000-2069}.
+
+@item
+Year values in the range @code{70-99} are converted to @code{1970-1999}.
+@end itemize
+
+Remember that these rules provide only reasonable guesses as to what your
+data mean. If the heuristics used by @strong{MySQL} don't produce the
+correct values, you should provide unambiguous input containing 4-digit
+year values.
+
+@code{ORDER BY} will sort 2 digit @code{YEAR/DATE/DATETIME} types properly.
+
+Note also that some functions like @code{MIN()} and @code{MAX()} will convert a
+@code{TIMESTAMP/DATE} to a number. This means that a timestamp with a 2
+digit year will not work properly with these functions. The fix in this
+case is to convert the @code{TIMESTAMP/DATE} to 4 digit year format or
+use something like @code{MIN(DATE_ADD(timestamp,INTERVAL 0 DAYS))}.
+
+@tindex DATETIME
+@tindex DATE
+@tindex TIMESTAMP
+@node DATETIME, TIME, Y2K issues, Date and time types
+@subsubsection The @code{DATETIME}, @code{DATE} and @code{TIMESTAMP} types
+
+The @code{DATETIME}, @code{DATE} and @code{TIMESTAMP} types are related.
+This section describes their characteristics, how they are similar and how
+they differ.
+
+The @code{DATETIME} type is used when you need values that contain both date
+and time information. @strong{MySQL} retrieves and displays @code{DATETIME}
+values in @code{'YYYY-MM-DD HH:MM:SS'} format. The supported range is
+@code{'1000-01-01 00:00:00'} to @code{'9999-12-31 23:59:59'}. (``Supported''
+means that although earlier values might work, there is no guarantee that
+they will.)
+
+The @code{DATE} type is used when you need only a date value, without a time
+part. @strong{MySQL} retrieves and displays @code{DATE} values in
+@code{'YYYY-MM-DD'} format. The supported range is @code{'1000-01-01'} to
+@code{'9999-12-31'}.
+
+The @code{TIMESTAMP} column type provides a type that you can use to
+automatically mark @code{INSERT} or @code{UPDATE} operations with the current
+date and time. If you have multiple @code{TIMESTAMP} columns, only the first
+one is updated automatically.
+
+Automatic updating of the first @code{TIMESTAMP} column occurs under any of
+the following conditions:
+
+@itemize @bullet
+@item
+The column is not specified explicitly in an @code{INSERT} or
+@code{LOAD DATA INFILE} statement.
+@item
+The column is not specified explicitly in an @code{UPDATE} statement and some
+other column changes value. (Note that an @code{UPDATE} that sets a column
+to the value it already has will not cause the @code{TIMESTAMP} column to be
+updated, because if you set a column to its current value, @strong{MySQL}
+ignores the update for efficiency.)
+@item
+You explicitly set the @code{TIMESTAMP} column to @code{NULL}.
+@end itemize
+
+@code{TIMESTAMP} columns other than the first may also be set to the current
+date and time. Just set the column to @code{NULL}, or to @code{NOW()}.
+
+You can set any @code{TIMESTAMP} column to a value different than the current
+date and time by setting it explicitly to the desired value. This is true
+even for the first @code{TIMESTAMP} column. You can use this property if,
+for example, you want a @code{TIMESTAMP} to be set to the current date and
+time when you create a row, but not to be changed whenever the row is updated
+later:
+
+@itemize @bullet
+@item
+Let @strong{MySQL} set the column when the row is created.
+This will initialize it to the current date and time.
+
+@item
+When you perform subsequent updates to other columns in the row, set
+the @code{TIMESTAMP} column explicitly to its current value.
+@end itemize
+
+On the other hand, you may find it just as easy to use a @code{DATETIME}
+column that you initialize to @code{NOW()} when the row is created and
+leave alone for subsequent updates.
+
+@code{TIMESTAMP} values may range from the beginning of 1970 to sometime in
+the year 2037, with a resolution of one second. Values are displayed as
+numbers.
+
+The format in which @strong{MySQL} retrieves and displays @code{TIMESTAMP}
+values depends on the display size, as illustrated by the table below. The
+`full' @code{TIMESTAMP} format is 14 digits, but @code{TIMESTAMP} columns may
+be created with shorter display sizes:
+
+@multitable @columnfractions .3 .7
+@item @strong{Column type} @tab @strong{Display format}
+@item @code{TIMESTAMP(14)} @tab @code{YYYYMMDDHHMMSS}
+@item @code{TIMESTAMP(12)} @tab @code{YYMMDDHHMMSS}
+@item @code{TIMESTAMP(10)} @tab @code{YYMMDDHHMM}
+@item @code{TIMESTAMP(8)} @tab @code{YYYYMMDD}
+@item @code{TIMESTAMP(6)} @tab @code{YYMMDD}
+@item @code{TIMESTAMP(4)} @tab @code{YYMM}
+@item @code{TIMESTAMP(2)} @tab @code{YY}
+@end multitable
+
+All @code{TIMESTAMP} columns have the same storage size, regardless of
+display size. The most common display sizes are 6, 8, 12, and 14. You can
+specify an arbitrary display size at table creation time, but values of 0 or
+greater than 14 are coerced to 14. Odd-valued sizes in the range from 1 to
+13 are coerced to the next higher even number.
+
+You can specify @code{DATETIME}, @code{DATE} and @code{TIMESTAMP} values using
+any of a common set of formats:
+
+@itemize @bullet
+@item
+As a string in either @code{'YYYY-MM-DD HH:MM:SS'} or @code{'YY-MM-DD
+HH:MM:SS'} format. A ``relaxed'' syntax is allowed---any punctuation
+character may be used as the delimiter between date parts or time parts.
+For example, @code{'98-12-31 11:30:45'}, @code{'98.12.31 11+30+45'},
+@code{'98/12/31 11*30*45'} and @code{'98@@12@@31 11^30^45'} are
+equivalent.
+
+@item
+As a string in either @code{'YYYY-MM-DD'} or @code{'YY-MM-DD'} format.
+A ``relaxed'' syntax is allowed here, too. For example, @code{'98-12-31'},
+@code{'98.12.31'}, @code{'98/12/31'} and @code{'98@@12@@31'} are
+equivalent.
+
+@item
+As a string with no delimiters in either @code{'YYYYMMDDHHMMSS'} or
+@code{'YYMMDDHHMMSS'} format, provided that the string makes sense as a
+date. For example, @code{'19970523091528'} and @code{'970523091528'} are
+interpreted as @code{'1997-05-23 09:15:28'}, but @code{'971122129015'} is
+illegal (it has a nonsensical minute part) and becomes @code{'0000-00-00
+00:00:00'}.
+
+@item
+As a string with no delimiters in either @code{'YYYYMMDD'} or @code{'YYMMDD'}
+format, provided that the string makes sense as a date. For example,
+@code{'19970523'} and @code{'970523'} are interpreted as
+@code{'1997-05-23'}, but @code{'971332'} is illegal (it has nonsensical month
+and day parts) and becomes @code{'0000-00-00'}.
+
+@item
+As a number in either @code{YYYYMMDDHHMMSS} or @code{YYMMDDHHMMSS}
+format, provided that the number makes sense as a date. For example,
+@code{19830905132800} and @code{830905132800} are interpreted as
+@code{'1983-09-05 13:28:00'}.
+
+@item
+As a number in either @code{YYYYMMDD} or @code{YYMMDD}
+format, provided that the number makes sense as a date. For example,
+@code{19830905} and @code{830905} are interpreted as @code{'1983-09-05'}.
+
+@item
+As the result of a function that returns a value that is acceptable
+in a @code{DATETIME}, @code{DATE} or @code{TIMESTAMP} context, such as
+@code{NOW()} or @code{CURRENT_DATE}.
+@end itemize
+
+Illegal @code{DATETIME}, @code{DATE} or @code{TIMESTAMP} values are converted
+to the ``zero'' value of the appropriate type (@code{'0000-00-00 00:00:00'},
+@code{'0000-00-00'} or @code{00000000000000}).
+
+For values specified as strings that include date part delimiters, it is not
+necessary to specify two digits for month or day values that are less than
+@code{10}. @code{'1979-6-9'} is the same as @code{'1979-06-09'}. Similarly,
+for values specified as strings that include time part delimiters, it is not
+necessary to specify two digits for hour, month or second values that are
+less than @code{10}. @code{'1979-10-30 1:2:3'} is the same as
+@code{'1979-10-30 01:02:03'}.
+
+Values specified as numbers should be 6, 8, 12 or 14 digits long. If the
+number is 8 or 14 digits long, it is assumed to be in @code{YYYYMMDD} or
+@code{YYYYMMDDHHMMSS} format and that the year is given by the first 4
+digits. If the number is 6 or 12 digits long, it is assumed to be in
+@code{YYMMDD} or @code{YYMMDDHHMMSS} format and that the year is given by the
+first 2 digits. Numbers that are not one of these lengths are interpreted
+as though padded with leading zeros to the closest length.
+
+Values specified as non-delimited strings are interpreted using their length
+as given. If the string is 8 or 14 characters long, the year is assumed to
+be given by the first 4 characters. Otherwise the year is assumed to be
+given by the first 2 characters. The string is interpreted from left to
+right to find year, month, day, hour, minute and second values, for as many
+parts as are present in the string. This means you should not use strings
+that have fewer than 6 characters. For example, if you specify @code{'9903'},
+thinking that will represent March, 1999, you will find that @strong{MySQL}
+inserts a ``zero'' date into your table. This is because the year and month
+values are @code{99} and @code{03}, but the day part is missing (zero), so
+the value is not a legal date.
+
+@code{TIMESTAMP} columns store legal values using the full precision with
+which the value was specified, regardless of the display size. This has
+several implications:
+
+@itemize @bullet
+@item
+Always specify year, month, and day, even if your column types are
+@code{TIMESTAMP(4)} or @code{TIMESTAMP(2)}. Otherwise, the value will not
+be a legal date and @code{0} will be stored.
+
+@item
+If you use @code{ALTER TABLE} to widen a narrow @code{TIMESTAMP} column,
+information will be displayed that previously was ``hidden''.
+
+@item
+Similarly, narrowing a @code{TIMESTAMP} column does not cause information to
+be lost, except in the sense that less information is shown when the values
+are displayed.
+
+@item
+Although @code{TIMESTAMP} values are stored to full precision, the only
+function that operates directly on the underlying stored value is
+@code{UNIX_TIMESTAMP()}. Other functions operate on the formatted retrieved
+value. This means you cannot use functions such as @code{HOUR()} or
+@code{SECOND()} unless the relevant part of the @code{TIMESTAMP} value is
+included in the formatted value. For example, the @code{HH} part of a
+@code{TIMESTAMP} column is not displayed unless the display size is at least
+10, so trying to use @code{HOUR()} on shorter @code{TIMESTAMP} values
+produces a meaningless result.
+@end itemize
+
+You can to some extent assign values of one date type to an object
+of a different date type. However, there may be some alteration
+of the value or loss of information:
+
+@itemize @bullet
+@item
+If you assign a @code{DATE} value to a @code{DATETIME} or @code{TIMESTAMP}
+object, the time part of the resulting value is set to @code{'00:00:00'},
+because the @code{DATE} value contains no time information.
+
+@item
+If you assign a @code{DATETIME} or @code{TIMESTAMP} value to a @code{DATE}
+object, the time part of the resulting value is deleted, because the
+@code{DATE} type stores no time information.
+
+@item
+Remember that although @code{DATETIME}, @code{DATE} and @code{TIMESTAMP}
+values all can be specified using the same set of formats, the types do not
+all have the same range of values. For example, @code{TIMESTAMP} values
+cannot be earlier than @code{1970} or later than @code{2037}. This means
+that a date such as @code{'1968-01-01'}, while legal as a @code{DATETIME} or
+@code{DATE} value, is not a valid @code{TIMESTAMP} value and will be
+converted to @code{0} if assigned to such an object.
+@end itemize
+
+Be aware of certain pitfalls when specifying date values:
+
+@itemize @bullet
+@item
+The relaxed format allowed for values specified as strings can be deceiving.
+For example, a value such as @code{'10:11:12'} might look like a time value
+because of the @samp{:} delimiter, but if used in a date context will be
+interpreted as the year @code{'2010-11-12'}. The value @code{'10:45:15'}
+will be converted to @code{'0000-00-00'} because @code{'45'} is not a legal
+month.
+
+@item
+Year values specified as two digits are ambiguous, because the century is
+unknown. @strong{MySQL} interprets 2-digit year values using the following
+rules:
+
+@itemize @minus
+@item
+Year values in the range @code{00-69} are converted to @code{2000-2069}.
+
+@item
+Year values in the range @code{70-99} are converted to @code{1970-1999}.
+@end itemize
+@end itemize
+
+@tindex TIME
+@node TIME, YEAR, DATETIME, Date and time types
+@subsubsection The @code{TIME} type
+
+@strong{MySQL} retrieves and displays @code{TIME} values in @code{'HH:MM:SS'}
+format (or @code{'HHH:MM:SS'} format for large hours values). @code{TIME}
+values may range from @code{'-838:59:59'} to @code{'838:59:59'}. The reason
+the hours part may be so large is that the @code{TIME} type may be used not
+only to represent a time of day (which must be less than 24 hours), but also
+elapsed time or a time interval between two events (which may be much greater
+than 24 hours, or even negative).
+
+You can specify @code{TIME} values in a variety of formats:
+
+@itemize @bullet
+@item
+As a string in @code{'D HH:MM:SS.fraction'} format. (Note that
+@strong{MySQL} doesn't yet store the fraction for the time column). One
+can also use one of the following ``relaxed'' syntax:
+
+@code{HH:MM:SS.fraction}, @code{HH:MM:SS}, @code{HH:MM}, @code{D HH:MM:SS},
+@code{D HH:MM}, @code{D HH} or @code{SS}. Here @code{D} is days between 0-33.
+
+@item
+As a string with no delimiters in @code{'HHMMSS'} format, provided that
+it makes sense as a time. For example, @code{'101112'} is understood as
+@code{'10:11:12'}, but @code{'109712'} is illegal (it has a nonsensical
+minute part) and becomes @code{'00:00:00'}.
+
+@item
+As a number in @code{HHMMSS} format, provided that it makes sense as a time.
+For example, @code{101112} is understood as @code{'10:11:12'}. The following
+alternative formats are also understood: @code{SS}, @code{MMSS},@code{HHMMSS},
+@code{HHMMSS.fraction}. Note that @strong{MySQL} doesn't yet store the
+fraction part.
+
+@item
+As the result of a function that returns a value that is acceptable
+in a @code{TIME} context, such as @code{CURRENT_TIME}.
+@end itemize
+
+For @code{TIME} values specified as strings that include a time part
+delimiter, it is not necessary to specify two digits for hours, minutes or
+seconds values that are less than @code{10}. @code{'8:3:2'} is the same as
+@code{'08:03:02'}.
+
+Be careful about assigning ``short'' @code{TIME} values to a @code{TIME}
+column. @strong{MySQL} interprets values using the assumption that the
+rightmost digits represent seconds. (@strong{MySQL} interprets @code{TIME}
+values as elapsed time, rather than as time of day.) For example, you might
+think of @code{'11:12'}, @code{'1112'} and @code{1112} as meaning
+@code{'11:12:00'} (12 minutes after 11 o'clock), but @strong{MySQL}
+interprets them as @code{'00:11:12'} (11 minutes, 12 seconds). Similarly,
+@code{'12'} and @code{12} are interpreted as @code{'00:00:12'}.
+
+Values that lie outside the @code{TIME} range
+but are otherwise legal are clipped to the appropriate
+endpoint of the range. For example, @code{'-850:00:00'} and
+@code{'850:00:00'} are converted to @code{'-838:59:59'} and
+@code{'838:59:59'}.
+
+Illegal @code{TIME} values are converted to @code{'00:00:00'}. Note that
+because @code{'00:00:00'} is itself a legal @code{TIME} value, there is no way
+to tell, from a value of @code{'00:00:00'} stored in a table, whether the
+original value was specified as @code{'00:00:00'} or whether it was illegal.
+
+@tindex YEAR
+@node YEAR, , TIME, Date and time types
+@subsubsection The @code{YEAR} type
+
+The @code{YEAR} type is a 1-byte type used for representing years.
+
+@strong{MySQL} retrieves and displays @code{YEAR} values in @code{YYYY}
+format. The range is @code{1901} to @code{2155}.
+
+You can specify @code{YEAR} values in a variety of formats:
+
+@itemize @bullet
+@item
+As a four-digit string in the range @code{'1901'} to @code{'2155'}.
+
+@item
+As a four-digit number in the range @code{1901} to @code{2155}.
+
+@item
+As a two-digit string in the range @code{'00'} to @code{'99'}. Values in the
+ranges @code{'00'} to @code{'69'} and @code{'70'} to @code{'99'} are
+converted to @code{YEAR} values in the ranges @code{2000} to @code{2069} and
+@code{1970} to @code{1999}.
+
+@item
+As a two-digit number in the range @code{1} to @code{99}. Values in the
+ranges @code{1} to @code{69} and @code{70} to @code{99} are converted to
+@code{YEAR} values in the ranges @code{2001} to @code{2069} and @code{1970}
+to @code{1999}. Note that the range for two-digit numbers is slightly
+different than the range for two-digit strings, because you cannot specify zero
+directly as a number and have it be interpreted as @code{2000}. You
+@emph{must} specify it as a string @code{'0'} or @code{'00'} or it will be
+interpreted as @code{0000}.
+
+@item
+As the result of a function that returns a value that is acceptable
+in a @code{YEAR} context, such as @code{NOW()}.
+@end itemize
+
+Illegal @code{YEAR} values are converted to @code{0000}.
+
+@node String types, Choosing types, Date and time types, Column types
+@subsection String types
+
+The string types are @code{CHAR}, @code{VARCHAR}, @code{BLOB}, @code{TEXT},
+@code{ENUM} and @code{SET}.
+
+@tindex CHAR
+@tindex VARCHAR
+@menu
+* CHAR:: The @code{CHAR} and @code{VARCHAR} types
+* BLOB:: The @code{BLOB} and @code{TEXT} types
+* ENUM:: The @code{ENUM} type
+* SET:: The @code{SET} type
+@end menu
+
+@node CHAR, BLOB, String types, String types
+@subsubsection The @code{CHAR} and @code{VARCHAR} types
+
+The @code{CHAR} and @code{VARCHAR} types are similar, but differ in the
+way they are stored and retrieved.
+
+The length of a @code{CHAR} column is fixed to the length that you declare
+when you create the table. The length can be any value between 1 and 255.
+(As of @strong{MySQL} 3.23, the length of @code{CHAR} may be 0 to 255.)
+When @code{CHAR} values are stored, they are right-padded with spaces to the
+specified length. When @code{CHAR} values are retrieved, trailing spaces are
+removed.
+
+Values in @code{VARCHAR} columns are variable-length strings. You can
+declare a @code{VARCHAR} column to be any length between 1 and 255, just as
+for @code{CHAR} columns. However, in contrast to @code{CHAR}, @code{VARCHAR}
+values are stored using only as many characters as are needed, plus one byte
+to record the length. Values are not padded; instead, trailing spaces are
+removed when values are stored. (This space removal differs from the ANSI
+SQL specification.)
+
+If you assign a value to a @code{CHAR} or @code{VARCHAR} column that
+exceeds the column's maximum length, the value is truncated to fit.
+
+The table below illustrates the differences between the two types of columns
+by showing the result of storing various string values into @code{CHAR(4)}
+and @code{VARCHAR(4)} columns:
+
+@c Need to use @(space) to make sure second column values retain spacing
+@c in output for table below.
+
+@multitable @columnfractions .2 .15 .2 .2 .25
+@item @strong{Value} @tab @code{CHAR(4)} @tab @strong{Storage required} @tab @code{VARCHAR(4)} @tab @strong{Storage required}
+@item @code{''} @tab @code{'@ @ @ @ '} @tab 4 bytes @tab @code{''} @tab 1 byte
+@item @code{'ab'} @tab @code{'ab@ @ '} @tab 4 bytes @tab @code{'ab'} @tab 3 bytes
+@item @code{'abcd'} @tab @code{'abcd'} @tab 4 bytes @tab @code{'abcd'} @tab 5 bytes
+@item @code{'abcdefgh'} @tab @code{'abcd'} @tab 4 bytes @tab @code{'abcd'} @tab 5 bytes
+@end multitable
+
+The values retrieved from the @code{CHAR(4)} and @code{VARCHAR(4)} columns
+will be the same in each case, because trailing spaces are removed from
+@code{CHAR} columns upon retrieval.
+
+Values in @code{CHAR} and @code{VARCHAR} columns are sorted and compared in
+case-insensitive fashion, unless the @code{BINARY} attribute was specified
+when the table was created. The @code{BINARY} attribute means that column
+values are sorted and compared in case-sensitive fashion according to the
+ASCII order of the machine where the @strong{MySQL} server is running.
+
+The @code{BINARY} attribute is ``sticky''. This means that if a column marked
+@code{BINARY} is used in an expression, the whole expression is compared as a
+@code{BINARY} value.
+
+@strong{MySQL} may silently change the type of a @code{CHAR} or @code{VARCHAR}
+column at table creation time.
+@xref{Silent column changes}.
+
+@tindex BLOB
+@tindex TEXT
+@node BLOB, ENUM, CHAR, String types
+@subsubsection The @code{BLOB} and @code{TEXT} types
+
+A @code{BLOB} is a binary large object that can hold a variable amount of
+data. The four @code{BLOB} types @code{TINYBLOB}, @code{BLOB},
+@code{MEDIUMBLOB} and @code{LONGBLOB} differ only in the maximum length of
+the values they can hold.
+@xref{Storage requirements}.
+
+The four @code{TEXT} types @code{TINYTEXT}, @code{TEXT}, @code{MEDIUMTEXT}
+and @code{LONGTEXT} correspond to the four @code{BLOB} types and have the
+same maximum lengths and storage requirements. The only difference between
+@code{BLOB} and @code{TEXT} types is that sorting and comparison is performed
+in case-sensitive fashion for @code{BLOB} values and case-insensitive fashion
+for @code{TEXT} values. In other words, a @code{TEXT} is a case-insensitive
+@code{BLOB}.
+
+If you assign a value to a @code{BLOB} or @code{TEXT} column that exceeds
+the column type's maximum length, the value is truncated to fit.
+
+In most respects, you can regard a @code{TEXT} column as a @code{VARCHAR}
+column that can be as big as you like. Similarly, you can regard a
+@code{BLOB} column as a @code{VARCHAR BINARY} column. The differences are:
+
+@itemize @bullet
+@item
+You can have indexes on @code{BLOB} and @code{TEXT} columns with
+@strong{MySQL} versions 3.23.2 and newer. Older versions of
+@strong{MySQL} did not support this.
+
+@item
+There is no trailing-space removal for @code{BLOB} and @code{TEXT} columns
+when values are stored, as there is for @code{VARCHAR} columns.
+
+@item
+@cindex Default values, @code{BLOB} and @code{TEXT} columns
+@cindex @code{BLOB} columns, default values
+@cindex @code{TEXT} columns, default values
+@code{BLOB} and @code{TEXT} columns cannot have @code{DEFAULT} values.
+@end itemize
+
+@strong{MyODBC} defines @code{BLOB} values as @code{LONGVARBINARY} and
+@code{TEXT} values as @code{LONGVARCHAR}.
+
+Because @code{BLOB} and @code{TEXT} values may be extremely long, you
+may run up against some constraints when using them:
+
+@itemize @bullet
+@item
+If you want to use @code{GROUP BY} or @code{ORDER BY} on a @code{BLOB} or
+@code{TEXT} column, you must convert the column value into a fixed-length
+object. The standard way to do this is with the @code{SUBSTRING}
+function. For example:
+
+@example
+mysql> select comment from tbl_name,substring(comment,20) as substr
+ ORDER BY substr;
+@end example
+
+If you don't do this, only the first @code{max_sort_length} bytes of the
+column are used when sorting. The default value of @code{max_sort_length} is
+1024; this value can be changed using the @code{-O} option when starting the
+@code{mysqld} server. You can group on an expression involving @code{BLOB} or
+@code{TEXT} values by specifying the column position or by using an alias:
+
+@example
+mysql> select id,substring(blob_col,1,100) from tbl_name
+ GROUP BY 2;
+mysql> select id,substring(blob_col,1,100) as b from tbl_name
+ GROUP BY b;
+@end example
+
+@item
+The maximum size of a @code{BLOB} or @code{TEXT} object is determined by its
+type, but the largest value you can actually transmit between the client and
+server is determined by the amount of available memory and the size of the
+communications buffers. You can change the message buffer size, but you must
+do so on both the server and client ends. @xref{Server parameters}.
+@end itemize
+
+Note that each @code{BLOB} or @code{TEXT} value is represented internally by
+a separately-allocated object. This is in contrast to all other column types,
+for which storage is allocated once per column when the table is opened.
+
+@tindex ENUM
+@node ENUM, SET, BLOB, String types
+@subsubsection The @code{ENUM} type
+
+An @code{ENUM} is a string object whose value normally is chosen from a list
+of allowed values that are enumerated explicitly in the column specification
+at table creation time.
+
+The value may also be the empty string (@code{""}) or @code{NULL} under
+certain circumstances:
+
+@itemize @bullet
+@item
+If you insert an invalid value into an @code{ENUM} (that is, a string not
+present in the list of allowed values), the empty string is inserted
+instead as a special error value.
+
+@item
+If an @code{ENUM} is declared @code{NULL}, @code{NULL} is also a legal value
+for the column, and the default value is @code{NULL}. If an @code{ENUM} is
+declared @code{NOT NULL}, the default value is the first element of the
+list of allowed values.
+@end itemize
+
+Each enumeration value has an index:
+
+@itemize @bullet
+@item
+Values from the list of allowable elements in the column specification are
+numbered beginning with 1.
+
+@item
+The index value of the empty string error value is 0. This means that you
+can use the following @code{SELECT} statement to find rows into which invalid
+@code{ENUM} values were assigned:
+
+@example
+mysql> SELECT * FROM tbl_name WHERE enum_col=0;
+@end example
+
+@item
+The index of the @code{NULL} value is @code{NULL}.
+@end itemize
+
+For example, a column specified as @code{ENUM("one", "two", "three")} can
+have any of the values shown below. The index of each value is also shown:
+
+@multitable @columnfractions .2 .8
+@item @strong{Value} @tab @strong{Index}
+@item @code{NULL} @tab @code{NULL}
+@item @code{""} @tab 0
+@item @code{"one"} @tab 1
+@item @code{"two"} @tab 2
+@item @code{"three"} @tab 3
+@end multitable
+
+An enumeration can have a maximum of 65535 elements.
+
+Lettercase is irrelevant when you assign values to an @code{ENUM} column.
+However, values retrieved from the column later have lettercase matching the
+values that were used to specify the allowable values at table creation time.
+
+If you retrieve an @code{ENUM} in a numeric context, the column value's index
+is returned. If you store a number into an @code{ENUM}, the number is
+treated as an index, and the the value stored is the enumeration member with
+that index. (However, this will not work with @code{LOAD DATA}, which treats
+all input as strings.)
+
+@code{ENUM} values are sorted according to the order in which the enumeration
+members were listed in the column specification. (In other words,
+@code{ENUM} values are sorted according to their index numbers.) For
+example, @code{"a"} sorts before @code{"b"} for @code{ENUM("a", "b")}, but
+@code{"b"} sorts before @code{"a"} for @code{ENUM("b", "a")}. The empty
+string sorts before non-empty strings, and @code{NULL} values sort before
+all other enumeration values.
+
+If you want to get all possible values for an @code{ENUM} column, you should
+use: @code{SHOW COLUMNS FROM table_name LIKE enum_column_name} and parse
+the @code{ENUM} definition in the second column.
+
+@tindex SET
+@node SET, , ENUM, String types
+@subsubsection The @code{SET} type
+
+A @code{SET} is a string object that can have zero or more values, each of
+which must be chosen from a list of allowed values specified when the table
+is created. @code{SET} column values that consist of multiple set members
+are specified with members separated by commas (@samp{,}). A consequence of
+this is that @code{SET} member values cannot themselves contain commas.
+
+For example, a column specified as @code{SET("one", "two") NOT NULL} can have
+any of these values:
+
+@example
+""
+"one"
+"two"
+"one,two"
+@end example
+
+
+A @code{SET} can have a maximum of 64 different members.
+
+@strong{MySQL} stores @code{SET} values numerically, with the low-order bit
+of the stored value corresponding to the first set member. If you retrieve a
+@code{SET} value in a numeric context, the value retrieved has bits set
+corresponding to the set members that make up the column value. If a number
+is stored into a @code{SET} column, the bits that are set in the binary
+representation of the number determine the set members in the column value.
+Suppose a column is specified as @code{SET("a","b","c","d")}. Then the
+members have the following bit values:
+
+@multitable @columnfractions .2 .2 .6
+@item @code{SET} @strong{member} @tab @strong{Decimal value} @tab @strong{Binary value}
+@item @code{a} @tab @code{1} @tab @code{0001}
+@item @code{b} @tab @code{2} @tab @code{0010}
+@item @code{c} @tab @code{4} @tab @code{0100}
+@item @code{d} @tab @code{8} @tab @code{1000}
+@end multitable
+
+If you assign a value of @code{9} to this column, that is @code{1001} in
+binary, so the first and fourth @code{SET} value members @code{"a"} and
+@code{"d"} are selected and the resulting value is @code{"a,d"}.
+
+For a value containing more than one @code{SET} element, it does not matter
+what order the elements are listed in when you insert the value. It also
+does not matter how many times a given element is listed in the value.
+When the value is retrieved later, each element in the value will appear
+once, with elements listed according to the order in which they were
+specified at table creation time. For example, if a column is specified as
+@code{SET("a","b","c","d")}, then @code{"a,d"}, @code{"d,a"} and
+@code{"d,a,a,d,d"} will all appear as @code{"a,d"} when retrieved.
+
+@code{SET} values are sorted numerically. @code{NULL} values sort before
+non-@code{NULL} @code{SET} values.
+
+Normally, you perform a @code{SELECT} on a @code{SET} column using
+the @code{LIKE} operator or the @code{FIND_IN_SET()} function:
+
+@example
+mysql> SELECT * FROM tbl_name WHERE set_col LIKE '%value%';
+mysql> SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)>0;
+@end example
+
+But the following will also work:
+
+@example
+mysql> SELECT * FROM tbl_name WHERE set_col = 'val1,val2';
+mysql> SELECT * FROM tbl_name WHERE set_col & 1;
+@end example
+
+The first of these statements looks for an exact match. The second looks
+for values containing the first set member.
+
+If you want to get all possible values for a @code{SET} column, you should
+use: @code{SHOW COLUMNS FROM table_name LIKE set_column_name} and parse
+the @code{SET} definition in the second column.
+
+@cindex Types, choosing
+@cindex Choosing types
+@node Choosing types, Indexes, String types, Column types
+@subsection Choosing the right type for a column
+
+For the most efficient use of storage, try to use the most precise type in
+all cases. For example, if an integer column will be used for values in the
+range between @code{1} and @code{99999}, @code{MEDIUMINT UNSIGNED} is the
+best type.
+
+Accurate representation of monetary values is a common problem. In
+@strong{MySQL}, you should use the @code{DECIMAL} type. This is stored as
+a string, so no loss of accuracy should occur. If accuracy is not
+too important, the @code{DOUBLE} type may also be good enough.
+
+For high precision, you can always convert to a fixed-point type stored
+in a @code{BIGINT}. This allows you to do all calculations with integers
+and convert results back to floating-point values only when necessary.
+
+@cindex Indexes
+@cindex Keys
+@node Indexes, Multiple-column indexes, Choosing types, Column types
+@subsection Column indexes
+
+All @strong{MySQL} column types can be indexed. Use of indexes on the
+relevant columns is the best way to improve the performance of @code{SELECT}
+operations.
+
+A table may have up to 16 indexes. The maximum index length is
+256 bytes, although this may be changed when compiling @strong{MySQL}.
+
+For @code{CHAR} and @code{VARCHAR} columns, you can index a prefix of a
+column. This is much faster and requires less disk space than indexing the
+whole column. The syntax to use in the @code{CREATE TABLE} statement to
+index a column prefix looks like this:
+
+@example
+KEY index_name (col_name(length))
+@end example
+
+The example below creates an index for the first 10 characters of the
+@code{name} column:
+
+@example
+mysql> CREATE TABLE test (
+ name CHAR(200) NOT NULL,
+ KEY index_name (name(10)));
+@end example
+
+For @code{BLOB} and @code{TEXT} columns, you must index a prefix of the
+column, you cannot index the entire thing.
+
+@node Multiple-column indexes, Other-vendor column types, Indexes, Column types
+@subsection Multiple-column indexes
+
+@strong{MySQL} can create indexes on multiple columns. An index may
+consist of up to 15 columns. (On @code{CHAR} and @code{VARCHAR} columns you
+can also use a prefix of the column as a part of an index).
+
+A multiple-column index can be considered a sorted array containing values
+that are created by concatenating the values of the indexed columns.
+
+@strong{MySQL} uses multiple-column indexes in such a way that queries are
+fast when you specify a known quantity for the first column of the index in a
+@code{WHERE} clause, even if you don't specify values for the other columns.
+
+Suppose a table is created using the following specification:
+
+@example
+mysql> CREATE TABLE test (
+ id INT NOT NULL,
+ last_name CHAR(30) NOT NULL,
+ first_name CHAR(30) NOT NULL,
+ PRIMARY KEY (id),
+ INDEX name (last_name,first_name));
+@end example
+
+Then the index @code{name} is an index over @code{last_name} and
+@code{first_name}. The index will be used for queries that specify
+values in a known range for @code{last_name}, or for both @code{last_name}
+and @code{first_name}.
+Therefore, the @code{name} index will be used in the following queries:
+
+@example
+mysql> SELECT * FROM test WHERE last_name="Widenius";
+
+mysql> SELECT * FROM test WHERE last_name="Widenius"
+ AND first_name="Michael";
+
+mysql> SELECT * FROM test WHERE last_name="Widenius"
+ AND (first_name="Michael" OR first_name="Monty");
+
+mysql> SELECT * FROM test WHERE last_name="Widenius"
+ AND first_name >="M" AND first_name < "N";
+@end example
+
+However, the @code{name} index will NOT be used in the following queries:
+
+@example
+mysql> SELECT * FROM test WHERE first_name="Michael";
+
+mysql> SELECT * FROM test WHERE last_name="Widenius"
+ OR first_name="Michael";
+@end example
+
+For more information on the manner in which @strong{MySQL} uses indexes to
+improve query performance, see @ref{MySQL indexes, , @strong{MySQL}
+indexes}.
+
+@cindex Type portability
+@node Other-vendor column types, , Multiple-column indexes, Column types
+@subsection Using column types from other database engines
+
+To make it easier to use code written for SQL implementations from other
+vendors, @strong{MySQL} maps column types as shown in the table below. These
+mappings make it easier to move table definitions from other database engines
+to @strong{MySQL}:
+
+@multitable @columnfractions .4 .6
+@item @strong{Other vendor type} @tab @strong{MySQL type}
+@item @code{BINARY(NUM)} @tab @code{CHAR(NUM) BINARY}
+@item @code{CHAR VARYING(NUM)} @tab @code{VARCHAR(NUM)}
+@item @code{FLOAT4} @tab @code{FLOAT}
+@item @code{FLOAT8} @tab @code{DOUBLE}
+@item @code{INT1} @tab @code{TINYINT}
+@item @code{INT2} @tab @code{SMALLINT}
+@item @code{INT3} @tab @code{MEDIUMINT}
+@item @code{INT4} @tab @code{INT}
+@item @code{INT8} @tab @code{BIGINT}
+@item @code{LONG VARBINARY} @tab @code{MEDIUMBLOB}
+@item @code{LONG VARCHAR} @tab @code{MEDIUMTEXT}
+@item @code{MIDDLEINT} @tab @code{MEDIUMINT}
+@item @code{VARBINARY(NUM)} @tab @code{VARCHAR(NUM) BINARY}
+@end multitable
+
+Column type mapping occurs at table creation time. If you create a table
+with types used by other vendors and then issue a @code{DESCRIBE tbl_name}
+statement, @strong{MySQL} reports the table structure using the equivalent
+@strong{MySQL} types.
+
+@cindex Functions for @code{SELECT} and @code{WHERE} clauses
+@node Functions, CREATE DATABASE, Column types, Reference
+@section Functions for use in @code{SELECT} and @code{WHERE} clauses
+
+A @code{select_expression} or @code{where_definition} in a SQL statement
+can consist of any expression using the functions described below.
+
+An expression that contains @code{NULL} always produces a @code{NULL} value
+unless otherwise indicated in the documentation for the operators and
+functions involved in the expression.
+
+@strong{Note:} There must be no whitespace between a function name and the
+parenthesis following it. This helps the @strong{MySQL} parser distinguish
+between function calls and references to tables or columns that happen to
+have the same name as a function. Spaces around arguments are permitted,
+though.
+
+@need 2000
+For the sake of brevity, examples display the output from the @code{mysql}
+program in abbreviated form. So this:
+
+@example
+mysql> select MOD(29,9);
+1 rows in set (0.00 sec)
+
++-----------+
+| mod(29,9) |
++-----------+
+| 2 |
++-----------+
+@end example
+
+Is displayed like this:
+
+@example
+mysql> select MOD(29,9);
+ -> 2
+@end example
+
+@menu
+* Grouping functions:: Grouping functions
+* Arithmetic functions:: Normal arithmetic operations
+* Bit functions:: Bit functions
+* Logical functions:: Logical operations
+* Comparison functions:: Comparison operators
+* String comparison functions:: String comparison functions
+* Casts:: Cast operators
+* Control flow functions:: Control flow functions
+* Mathematical functions:: Mathematical functions
+* String functions:: String functions
+* Date and time functions:: Date and time functions
+* Miscellaneous functions:: Miscellaneous functions
+* Group by functions:: Functions for @code{GROUP BY} clause
+@end menu
+
+@node Grouping functions, Arithmetic functions, Functions, Functions
+@subsection Grouping functions
+@cindex Grouping of expressions
+@table @code
+
+@findex () (parentheses)
+@findex parentheses ( and )
+@item ( ... )
+Parentheses. Use these to force the order of evaluation in an expression.
+@example
+mysql> select 1+2*3;
+ -> 7
+mysql> select (1+2)*3;
+ -> 9
+@end example
+@end table
+
+@node Arithmetic functions, Bit functions, Grouping functions, Functions
+@subsection Normal arithmetic operations
+
+The usual arithmetic operators are available. Note that in the case of
+@code{-}, @code{+} and @code{*}, the result is calculated with @code{BIGINT}
+(64-bit) precision if both arguments are integers!
+
+@cindex Arithmetic expressions
+@table @code
+@findex + (addition)
+@findex addition (+)
+@item +
+Addition
+@example
+mysql> select 3+5;
+ -> 8
+@end example
+
+@findex - (subtraction)
+@findex subtraction (-)
+@item -
+Subtraction
+@example
+mysql> select 3-5;
+ -> -2
+@end example
+
+@findex * (multiplication)
+@findex multiplication (*)
+@item *
+Multiplication
+@example
+mysql> select 3*5;
+ -> 15
+mysql> select 18014398509481984*18014398509481984.0;
+ -> 324518553658426726783156020576256.0
+mysql> select 18014398509481984*18014398509481984;
+ -> 0
+@end example
+
+The result of the last expression is incorrect because the result of the integer
+multiplication exceeds the 64-bit range of @code{BIGINT} calculations.
+
+@findex / (division)
+@findex division (/)
+@item /
+Division
+@example
+mysql> select 3/5;
+ -> 0.60
+@end example
+
+Division by zero produces a @code{NULL} result:
+
+@example
+mysql> select 102/(1-1);
+ -> NULL
+@end example
+
+A division will be calculated with @code{BIGINT} arithmetic only if performed
+in a context where its result is converted to an integer!
+@end table
+
+@findex Arithmetic functions
+@findex Bit functions
+@findex Functions, arithmetic
+@findex Functions, bit
+@node Bit functions, Logical functions, Arithmetic functions, Functions
+@subsection Bit functions
+
+@strong{MySQL} uses @code{BIGINT} (64-bit) arithmetic for bit operations, so
+these operators have a maximum range of 64 bits.
+
+@table @code
+@findex | (bitwise OR)
+@findex OR, bitwise
+@item |
+Bitwise OR
+@example
+mysql> select 29 | 15;
+ -> 31
+@end example
+
+@findex & (bitwise AND)
+@findex AND, bitwise
+@item &
+Bitwise AND
+@example
+mysql> select 29 & 15;
+ -> 13
+@end example
+
+@findex << (left shift)
+@item <<
+Shifts a longlong (@code{BIGINT}) number to the left.
+@example
+mysql> select 1 << 2
+ -> 4
+@end example
+
+@findex >> (right shift)
+@item >>
+Shifts a longlong (@code{BIGINT}) number to the right.
+@example
+mysql> select 4 >> 2
+ -> 1
+@end example
+
+@findex ~
+@item ~
+Invert all bits.
+@example
+mysql> select 5 & ~1
+ -> 4
+@end example
+
+@findex BIT_COUNT()
+@item BIT_COUNT(N)
+Returns the number of bits that are set in the argument @code{N}.
+@example
+mysql> select BIT_COUNT(29);
+ -> 4
+@end example
+@end table
+
+@findex Logical functions
+@findex Functions, logical
+@node Logical functions, Comparison functions, Bit functions, Functions
+@subsection Logical operations
+
+All logical functions return @code{1} (TRUE) or @code{0} (FALSE).
+
+@table @code
+@findex NOT, logical
+@findex ! (logical NOT)
+@item NOT
+@itemx !
+Logical NOT. Returns @code{1} if the argument is @code{0}, otherwise returns
+@code{0}.
+Exception: @code{NOT NULL} returns @code{NULL}.
+@example
+mysql> select NOT 1;
+ -> 0
+mysql> select NOT NULL;
+ -> NULL
+mysql> select ! (1+1);
+ -> 0
+mysql> select ! 1+1;
+ -> 1
+@end example
+The last example returns @code{1} because the expression evaluates
+the same way as @code{(!1)+1}.
+
+@findex OR, logical
+@findex || (logical OR)
+@item OR
+@itemx ||
+Logical OR. Returns @code{1} if either argument is not @code{0} and not
+@code{NULL}.
+@example
+mysql> select 1 || 0;
+ -> 1
+mysql> select 0 || 0;
+ -> 0
+mysql> select 1 || NULL;
+ -> 1
+
+@end example
+
+@findex AND, logical
+@findex && (logical AND)
+@item AND
+@itemx &&
+Logical AND. Returns @code{0} if either argument is @code{0} or @code{NULL},
+otherwise returns @code{1}.
+@example
+mysql> select 1 && NULL;
+ -> 0
+mysql> select 1 && 0;
+ -> 0
+@end example
+@end table
+
+@cindex Casts
+@cindex Type conversions
+@findex Comparison operators
+@node Comparison functions, String comparison functions, Logical functions, Functions
+@subsection Comparison operators
+
+Comparison operations result in a value of @code{1} (TRUE), @code{0} (FALSE)
+or @code{NULL}. These functions work for both numbers and strings. Strings
+are automatically converted to numbers and numbers to strings as needed (as
+in Perl).
+
+@strong{MySQL} performs comparisons using the following
+rules:
+
+@itemize @bullet
+@item
+If one or both arguments are @code{NULL}, the result of the comparison
+is @code{NULL}, except for the @code{<=>} operator.
+
+@item
+If both arguments in a comparison operation are strings, they are compared as
+strings.
+
+@item
+If both arguments are integers, they are compared as integers.
+
+@item
+Hexadecimal values are treated as binary strings if not compared to a number.
+
+@item
+@cindex ODBC compatibility
+@cindex Compatibility, with ODBC
+If one of the arguments is a @code{TIMESTAMP} or @code{DATETIME} column and
+the other argument is a constant, the constant is converted
+to a timestamp before the comparison is performed. This is done to be more
+ODBC-friendly.
+
+@item
+In all other cases, the arguments are compared as floating-point (real)
+numbers.
+@end itemize
+
+By default, string comparisons are done in case-independent fashion using the
+current character set (ISO-8859-1 Latin1 by default, which also works
+excellently for English).
+
+The examples below illustrate conversion of strings to numbers for comparison
+operations:
+
+@example
+mysql> SELECT 1 > '6x';
+ -> 0
+mysql> SELECT 7 > '6x';
+ -> 1
+mysql> SELECT 0 > 'x6';
+ -> 0
+mysql> SELECT 0 = 'x6';
+ -> 1
+@end example
+
+@table @code
+@findex = (equal)
+@findex equal (=)
+@item =
+Equal
+@example
+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
+@end example
+
+@findex <> (not equal)
+@findex not equal (<>)
+@findex != (not equal)
+@findex not equal (!=)
+@item <>
+@itemx !=
+Not equal
+@example
+mysql> select '.01' <> '0.01';
+ -> 1
+mysql> select .01 <> '0.01';
+ -> 0
+mysql> select 'zapp' <> 'zappp';
+ -> 1
+@end example
+
+@findex <= (less than or equal)
+@findex less than or equal (<=)
+@item <=
+Less than or equal
+@example
+mysql> select 0.1 <= 2;
+ -> 1
+@end example
+
+@findex < (less than)
+@findex less than (<)
+@item <
+Less than
+@example
+mysql> select 2 <= 2;
+ -> 1
+@end example
+
+@findex >= (greater than or equal)
+@findex greater than or equal (>=)
+@item >=
+Greater than or equal
+@example
+mysql> select 2 >= 2;
+ -> 1
+@end example
+
+@findex > (greater than)
+@findex greater than (>)
+@item >
+Greater than
+@example
+mysql> select 2 > 2;
+ -> 0
+@end example
+
+@findex <=> (Equal to)
+@item <=>
+Null safe equal
+@example
+mysql> select 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
+ -> 1 1 0
+@end example
+
+@findex IS NULL
+@findex IS NOT NULL
+@item IS NULL
+@itemx IS NOT NULL
+Test whether or not a value is or is not @code{NULL}
+@example
+mysql> select 1 IS NULL, 0 IS NULL, NULL IS NULL:
+ -> 0 0 1
+mysql> select 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL;
+ -> 1 1 0
+@end example
+
+@findex BETWEEN ... AND
+@item expr BETWEEN min AND max
+If @code{expr} is greater than or equal to @code{min} and @code{expr} is
+less than or equal to @code{max}, @code{BETWEEN} returns @code{1},
+otherwise it returns @code{0}. This is equivalent to the expression
+@code{(min <= expr AND expr <= max)} if all the arguments are of the
+same type. The first argument (@code{expr}) determines how the
+comparison is performed as follows:
+
+@itemize @bullet
+@item
+If @code{expr} is a @code{TIMESTAMP}, @code{DATE} or @code{DATETIME}
+column, min and max are formatted to the same format if they
+are constants.
+@item
+If @code{expr} is a case-insensitive string expression, a case-insensitive
+string comparison is done.
+@item
+If @code{expr} is a case-sensitive string expression, a case-sensitive
+string comparison is done.
+@item
+If @code{expr} is an integer expression, an integer comparison is done.
+@item
+Otherwise, a floating-point (real) comparison is done.
+@end itemize
+
+@example
+mysql> select 1 BETWEEN 2 AND 3;
+ -> 0
+mysql> select 'b' BETWEEN 'a' AND 'c';
+ -> 1
+mysql> select 2 BETWEEN 2 AND '3';
+ -> 1
+mysql> select 2 BETWEEN 2 AND 'x-3';
+ -> 0
+@end example
+
+@findex IN
+@item expr IN (value,...)
+Returns @code{1} if @code{expr} is any of the values in the @code{IN} list,
+else returns @code{0}. If all values are constants, then all values are
+evaluated according to the type of @code{expr} and sorted. The search for the
+item is then done using a binary search. This means @code{IN} is very quick
+if the @code{IN} value list consists entirely of constants. If @code{expr}
+is a case-sensitive string expression, the string comparison is performed in
+case-sensitive fashion.
+
+@example
+mysql> select 2 IN (0,3,5,'wefwf');
+ -> 0
+mysql> select 'wefwf' IN (0,3,5,'wefwf');
+ -> 1
+@end example
+
+@findex NOT IN
+@item expr NOT IN (value,...)
+Same as @code{NOT (expr IN (value,...))}.
+
+@findex ISNULL()
+@item ISNULL(expr)
+If @code{expr} is @code{NULL}, @code{ISNULL()} returns @code{1}, otherwise
+it returns @code{0}.
+@example
+mysql> select ISNULL(1+1);
+ -> 0
+mysql> select ISNULL(1/0);
+ -> 1
+@end example
+
+Note that a comparison of @code{NULL} values using @code{=} will always be
+false!
+
+@findex COALESCE()
+@item COALESCE(list)
+Returns first non-@code{NULL} element in list.
+
+@example
+mysql> select COALESCE(NULL,1);
+ -> 1
+mysql> select COALESCE(NULL,NULL,NULL);
+ -> NULL
+@end example
+
+@findex INTERVAL()
+@item INTERVAL(N,N1,N2,N3,...)
+Returns @code{0} if @code{N} < @code{N1}, @code{1} if @code{N} < @code{N2}
+and so on. All arguments are treated as integers. It is required that
+@code{N1} < @code{N2} < @code{N3} < @code{...} < @code{Nn} for this function
+to work correctly. This is because a binary search is used (very fast).
+
+@example
+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
+@end example
+@end table
+
+@findex String comparison functions
+@findex Functions, string comparison
+@node String comparison functions, Casts, Comparison functions, Functions
+@subsection String comparison functions
+
+@cindex Case sensitivity, in string comparisons
+@cindex String comparisons, case sensitivity
+Normally, if any expression in a string comparison is case sensitive, the
+comparison is performed in case-sensitive fashion.
+
+@table @code
+@findex LIKE
+@item expr LIKE pat [ESCAPE 'escape-char']
+Pattern matching using
+SQL simple regular expression comparison. Returns @code{1} (TRUE) or @code{0}
+(FALSE). With @code{LIKE} you can use the following two wildcard characters
+in the pattern:
+
+@multitable @columnfractions .1 .9
+@item @code{%} @tab Matches any number of characters, even zero characters
+@item @code{_} @tab Matches exactly one character
+@end multitable
+
+@example
+mysql> select 'David!' LIKE 'David_';
+ -> 1
+mysql> select 'David!' LIKE '%D%v%';
+ -> 1
+@end example
+
+To test for literal instances of a wildcard character, precede the character
+with the escape character. If you don't specify the @code{ESCAPE} character,
+@samp{\} is assumed:
+
+@multitable @columnfractions .1 .9
+@item @code{\%} @tab Matches one @code{%} character
+@item @code{\_} @tab Matches one @code{_} character
+@end multitable
+
+@example
+mysql> select 'David!' LIKE 'David\_';
+ -> 0
+mysql> select 'David_' LIKE 'David\_';
+ -> 1
+@end example
+
+To specify a different escape character, use the @code{ESCAPE} clause:
+
+@example
+mysql> select 'David_' LIKE 'David|_' ESCAPE '|';
+ -> 1
+@end example
+
+@code{LIKE} is allowed on numeric expressions! (This is a @strong{MySQL}
+extension to the ANSI SQL @code{LIKE}.)
+
+@example
+mysql> select 10 LIKE '1%';
+ -> 1
+@end example
+
+Note: Because @strong{MySQL} uses the C escape syntax in strings (e.g.,
+@samp{\n}), you must double any @samp{\} that you use in your @code{LIKE}
+strings. For example, to search for @samp{\n}, specify it as @samp{\\n}. To
+search for @samp{\}, specify it as @samp{\\\\} (the backslashes are stripped
+once by the parser, and another time when the pattern match is done, leaving
+a single backslash to be matched).
+
+@findex NOT LIKE
+@item expr NOT LIKE pat [ESCAPE 'escape-char']
+Same as @code{NOT (expr LIKE pat [ESCAPE 'escape-char'])}.
+
+@cindex mSQL compatibility
+@cindex Compatibility, with mSQL
+@findex REGEXP
+@findex RLIKE
+@item expr REGEXP pat
+@itemx expr RLIKE pat
+Performs a pattern match of a string expression @code{expr} against a pattern
+@code{pat}. The pattern can be an extended regular expression.
+@xref{Regexp}. Returns @code{1} if @code{expr} matches @code{pat}, otherwise
+returns @code{0}. @code{RLIKE} is a synonym for @code{REGEXP}, provided for
+@code{mSQL} compatibility. Note: Because @strong{MySQL} uses the C escape
+syntax in strings (e.g., @samp{\n}), you must double any @samp{\} that you
+use in your @code{REGEXP} strings. In @code{MySQL} 3.23.4
+@code{REGEXP} is case insensitive for normal (not binary) strings.
+
+@example
+mysql> select 'Monty!' REGEXP 'm%y%%';
+ -> 0
+mysql> select 'Monty!' REGEXP '.*';
+ -> 1
+mysql> select 'new*\n*line' REGEXP 'new\\*.\\*line';
+ -> 1
+mysql> select "a" REGEXP "A", "a" REGEXP BINARY "A";
+ -> 1 0
+@end example
+
+@item
+@code{REGEXP} and @code{RLIKE} use the current character set (ISO-8859-1
+Latin1 by default) when deciding the type of a character.
+
+@findex NOT REGEXP
+@item expr NOT REGEXP pat
+@itemx expr NOT RLIKE pat
+Same as @code{NOT (expr REGEXP pat)}.
+
+@findex STRCMP()
+@item STRCMP(expr1,expr2)
+@code{STRCMP()}
+returns @code{0} if the strings are the same, @code{-1} if the first
+argument is smaller than the second according to the current sort order,
+and @code{1} otherwise.
+
+@example
+mysql> select STRCMP('text', 'text2');
+ -> -1
+mysql> select STRCMP('text2', 'text');
+ -> 1
+mysql> select STRCMP('text', 'text');
+ -> 0
+@end example
+@end table
+
+@findex Casts
+@node Casts, Control flow functions, String comparison functions, Functions
+@subsection Cast operators
+
+@table @code
+@findex BINARY
+@item @code{BINARY}
+The @code{BINARY} operator casts the string following it to a binary string.
+This is an easy way to force a column comparison to be case sensitive even
+if the column isn't defined as @code{BINARY} or @code{BLOB}.
+@example
+mysql> select "a" = "A";
+ -> 1
+mysql> select BINARY "a" = "A";
+ -> 0
+@end example
+
+@code{BINARY} was introduced in @strong{MySQL} 3.23.0
+@end table
+
+@findex Control flow functions
+@findex Functions, control flow
+@node Control flow functions, Mathematical functions, Casts, Functions
+@subsection Control flow functions
+
+@table @code
+@findex IFNULL()
+@item IFNULL(expr1,expr2)
+If @code{expr1} is not @code{NULL}, @code{IFNULL()} returns @code{expr1},
+else it returns @code{expr2}. @code{IFNULL()} returns a numeric or string
+value, depending on the context in which it is used.
+@example
+mysql> select IFNULL(1,0);
+ -> 1
+mysql> select IFNULL(NULL,10);
+ -> 10
+mysql> select IFNULL(1/0,10);
+ -> 10
+mysql> select IFNULL(1/0,'yes');
+ -> 'yes'
+@end example
+
+@findex NULLIF()
+@item NULLIF(expr1,expr2)
+If @code{expr1 = expr2} is true, return @code{NULL} else return @code{expr1}.
+This is the same as @code{CASE WHEN x = y THEN NULL ELSE x END}
+@example
+mysql> select NULLIF(1,1);
+ -> NULL
+mysql> select NULLIF(1,2);
+ -> 1
+@end example
+
+Note that @code{expr1} is evaluated twice in @strong{MySQL} if the arguments
+are equal.
+
+@findex IF()
+@item IF(expr1,expr2,expr3)
+If @code{expr1} is TRUE (@code{expr1 <> 0} and @code{expr1 <> NULL}) then
+@code{IF()} returns @code{expr2}, else it returns @code{expr3}.
+@code{IF()} returns a numeric or string value, depending on the context
+in which it is used.
+
+@example
+mysql> select IF(1>2,2,3);
+ -> 3
+mysql> select IF(1<2,'yes','no');
+ -> 'yes'
+mysql> select IF(strcmp('test','test1'),'no','yes');
+ -> 'no'
+@end example
+
+@code{expr1} is evaluated as an integer value, which means that if you are
+testing floating-point or string values, you should do so using a comparison
+operation.
+
+@example
+mysql> select IF(0.1,1,0);
+ -> 0
+mysql> select IF(0.1<>0,1,0);
+ -> 1
+@end example
+
+In the first case above, @code{IF(0.1)} returns @code{0} because @code{0.1}
+is converted to an integer value, resulting in a test of @code{IF(0)}. This
+may not be what you expect. In the second case, the comparison tests the
+original floating-point value to see whether it is non-zero. The result
+of the comparison is used as an integer.
+
+The default return type of @code{IF()} (which may matter when it stored into
+a temporary table) is calculated in @strong{MySQL} 3.23 as follows:
+
+@multitable @columnfractions .7 .3
+@item expr2 or expr3 returns string @tab string
+@item expr2 or expr3 returns a floating point value @tab floating point
+@item expr2 or expr3 returns an integer @tab integer
+@end multitable
+
+@findex CASE
+@item CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...] [ELSE result] END
+@item CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END
+
+The first version returns the @code{result} where
+@code{value=compare-value}. The second version returns the result for
+the first condition which is true. If there was no matching result
+value, then the result after @code{ELSE} is returned. If there is no
+@code{ELSE} part then @code{NULL} is returned.
+
+@example
+mysql> SELECT CASE 1 WHEN 1 THEN "one" WHEN 2 THEN "two" ELSE "more" END;
+ -> "one"
+mysql> SELECT CASE WHEN 1>0 THEN "true" ELSE "false" END;
+ -> "true"
+mysql> SELECT CASE BINARY "B" when "a" then 1 when "b" then 2 END;
+ -> NULL
+@end example
+@end table
+
+@findex Mathematical functions
+@findex Functions, mathematical
+@node Mathematical functions, String functions, Control flow functions, Functions
+@subsection Mathematical functions
+All mathematical functions return @code{NULL} in case of an error.
+
+@table @code
+@findex - (unary minus)
+@findex minus, unary (-)
+@findex unary minus (-)
+@item -
+Unary minus. Changes the sign of the argument.
+@example
+mysql> select - 2;
+ -> -2
+@end example
+
+Note that if this operator is used with a @code{BIGINT}, the return value is a
+@code{BIGINT}! This means that you should avoid using @code{-} on integers that
+may have the value of @code{-2^63}!
+
+@findex ABS()
+@item ABS(X)
+Returns the absolute value of @code{X}.
+@example
+mysql> select ABS(2);
+ -> 2
+mysql> select ABS(-32);
+ -> 32
+@end example
+
+This function is safe to use with @code{BIGINT} values.
+
+@findex SIGN()
+@item SIGN(X)
+Returns the sign of the argument as @code{-1}, @code{0} or @code{1}, depending
+on whether @code{X} is negative, zero, or positive.
+@example
+mysql> select SIGN(-32);
+ -> -1
+mysql> select SIGN(0);
+ -> 0
+mysql> select SIGN(234);
+ -> 1
+@end example
+
+@findex MOD()
+@findex % (modulo)
+@findex modulo (%)
+@item MOD(N,M)
+@itemx %
+Modulo (like the @code{%} operator in C).
+Returns the remainder of @code{N} divided by @code{M}.
+@example
+mysql> select MOD(234, 10);
+ -> 4
+mysql> select 253 % 7;
+ -> 1
+mysql> select MOD(29,9);
+ -> 2
+@end example
+
+This function is safe to use with @code{BIGINT} values.
+
+@findex FLOOR()
+@item FLOOR(X)
+Returns the largest integer value not greater than @code{X}.
+@example
+mysql> select FLOOR(1.23);
+ -> 1
+mysql> select FLOOR(-1.23);
+ -> -2
+@end example
+
+Note that the return value is converted to a @code{BIGINT}!
+
+@findex CEILING()
+@item CEILING(X)
+Returns the smallest integer value not less than @code{X}.
+@example
+mysql> select CEILING(1.23);
+ -> 2
+mysql> select CEILING(-1.23);
+ -> -1
+@end example
+
+Note that the return value is converted to a @code{BIGINT}!
+
+@findex ROUND()
+@item ROUND(X)
+Returns the argument @code{X}, rounded to the nearest integer.
+@example
+mysql> select ROUND(-1.23);
+ -> -1
+mysql> select ROUND(-1.58);
+ -> -2
+mysql> select ROUND(1.58);
+ -> 2
+@end example
+
+@findex ROUND()
+@item ROUND(X,D)
+Returns the argument @code{X}, rounded to a number with @code{D} decimals.
+If @code{D} is @code{0}, the result will have no decimal point or fractional
+part.
+
+@example
+mysql> select ROUND(1.298, 1);
+ -> 1.3
+mysql> select ROUND(1.298, 0);
+ -> 1
+@end example
+
+@findex EXP()
+@item EXP(X)
+Returns the value of @code{e} (the base of natural logarithms) raised to
+the power of @code{X}.
+@example
+mysql> select EXP(2);
+ -> 7.389056
+mysql> select EXP(-2);
+ -> 0.135335
+@end example
+@findex LOG()
+@item LOG(X)
+Returns the natural logarithm of @code{X}.
+@example
+mysql> select LOG(2);
+ -> 0.693147
+mysql> select LOG(-2);
+ -> NULL
+@end example
+If you want the log of a number @code{X} to some arbitary base @code{B}, use
+the formula @code{LOG(X)/LOG(B)}.
+
+@findex LOG10()
+@item LOG10(X)
+Returns the base-10 logarithm of @code{X}.
+@example
+mysql> select LOG10(2);
+ -> 0.301030
+mysql> select LOG10(100);
+ -> 2.000000
+mysql> select LOG10(-100);
+ -> NULL
+@end example
+
+@findex POW()
+@findex POWER()
+@item POW(X,Y)
+@itemx POWER(X,Y)
+Returns the value of @code{X} raised to the power of @code{Y}.
+@example
+mysql> select POW(2,2);
+ -> 4.000000
+mysql> select POW(2,-2);
+ -> 0.250000
+@end example
+
+@findex SQRT()
+@item SQRT(X)
+Returns the non-negative square root of @code{X}.
+@example
+mysql> select SQRT(4);
+ -> 2.000000
+mysql> select SQRT(20);
+ -> 4.472136
+@end example
+
+@findex PI()
+@item PI()
+Returns the value of PI.
+@example
+mysql> select PI();
+ -> 3.141593
+@end example
+
+@findex COS()
+@item COS(X)
+Returns the cosine of @code{X}, where @code{X} is given in radians.
+@example
+mysql> select COS(PI());
+ -> -1.000000
+@end example
+
+@findex SIN()
+@item SIN(X)
+Returns the sine of @code{X}, where @code{X} is given in radians.
+@example
+mysql> select SIN(PI());
+ -> 0.000000
+@end example
+
+@findex TAN()
+@item TAN(X)
+Returns the tangent of @code{X}, where @code{X} is given in radians.
+@example
+mysql> select TAN(PI()+1);
+ -> 1.557408
+@end example
+
+@findex ACOS()
+@item ACOS(X)
+Returns the arc cosine of @code{X}, that is, the value whose cosine is
+@code{X}. Returns @code{NULL} if @code{X} is not in the range @code{-1} to
+@code{1}.
+@example
+mysql> select ACOS(1);
+ -> 0.000000
+mysql> select ACOS(1.0001);
+ -> NULL
+mysql> select ACOS(0);
+ -> 1.570796
+@end example
+
+@findex ASIN()
+@item ASIN(X)
+Returns the arc sine of @code{X}, that is, the value whose sine is
+@code{X}. Returns @code{NULL} if @code{X} is not in the range @code{-1} to
+@code{1}.
+@example
+mysql> select ASIN(0.2);
+ -> 0.201358
+mysql> select ASIN('foo');
+ -> 0.000000
+@end example
+
+@findex ATAN()
+@item ATAN(X)
+Returns the arc tangent of @code{X}, that is, the value whose tangent is
+@code{X}.
+@example
+mysql> select ATAN(2);
+ -> 1.107149
+mysql> select ATAN(-2);
+ -> -1.107149
+@end example
+
+@findex ATAN2()
+@item ATAN2(X,Y)
+Returns the arc tangent of the two variables @code{X} and @code{Y}. It is
+similar to calculating the arc tangent of @code{Y / X}, except that the
+signs of both arguments are used to determine the quadrant of the
+result.
+@example
+mysql> select ATAN(-2,2);
+ -> -0.785398
+mysql> select ATAN(PI(),0);
+ -> 1.570796
+@end example
+
+@findex COT()
+@item COT(X)
+Returns the cotangent of @code{X}.
+@example
+mysql> select COT(12);
+ -> -1.57267341
+mysql> select COT(0);
+ -> NULL
+@end example
+
+@findex RAND()
+@item RAND()
+@itemx RAND(N)
+Returns a random floating-point value in the range @code{0} to @code{1.0}.
+If an integer argument @code{N} is specified, it is used as the seed value.
+@example
+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
+@end example
+You can't use a column with @code{RAND()} values in an @code{ORDER BY}
+clause, because @code{ORDER BY} would evaluate the column multiple times.
+In @strong{MySQL} 3.23, you can however do:
+@code{SELECT * FROM table_name ORDER BY RAND()}
+
+This is useful to get a random sample of a set @code{SELECT * FROM
+table1,table2 WHERE a=b AND c<d ORDER BY RAND() LIMIT 1000}.
+
+Note that a @code{RAND()} in a @code{WHERE} clause will be re-evaluated
+every time the @code{WHERE} is executed.
+
+@findex LEAST()
+@item LEAST(X,Y,...)
+With two or more arguments, returns the smallest (minimum-valued) argument.
+The arguments are compared using the following rules:
+
+@itemize @bullet
+@item
+If the return value is used in an @code{INTEGER} context, or all arguments
+are integer-valued, they are compared as integers.
+
+@item
+If the return value is used in a @code{REAL} context, or all arguments are
+real-valued, they are compared as reals.
+
+@item
+If any argument is a case-sensitive string, the arguments are compared
+as case-sensitive strings.
+
+@item
+In other cases, the arguments are compared as case-insensitive strings.
+@end itemize
+
+@example
+mysql> select LEAST(2,0);
+ -> 0
+mysql> select LEAST(34.0,3.0,5.0,767.0);
+ -> 3.0
+mysql> select LEAST("B","A","C");
+ -> "A"
+@end example
+In @strong{MySQL} versions prior to 3.22.5, you can use @code{MIN()} instead
+of @code{LEAST}.
+
+@findex GREATEST()
+@item GREATEST(X,Y,...)
+Returns the largest (maximum-valued) argument.
+The arguments are compared using the same rules as for @code{LEAST}.
+@example
+mysql> select GREATEST(2,0);
+ -> 2
+mysql> select GREATEST(34.0,3.0,5.0,767.0);
+ -> 767.0
+mysql> select GREATEST("B","A","C");
+ -> "C"
+@end example
+In @strong{MySQL} versions prior to 3.22.5, you can use @code{MAX()} instead
+of @code{GREATEST}.
+
+@findex DEGREES()
+@item DEGREES(X)
+Returns the argument @code{X}, converted from radians to degrees.
+@example
+mysql> select DEGREES(PI());
+ -> 180.000000
+@end example
+
+@findex RADIANS()
+@item RADIANS(X)
+Returns the argument @code{X}, converted from degrees to radians.
+@example
+mysql> select RADIANS(90);
+ -> 1.570796
+@end example
+
+@findex TRUNCATE()
+@item TRUNCATE(X,D)
+Returns the number @code{X}, truncated to @code{D} decimals. If @code{D}
+is @code{0}, the result will have no decimal point or fractional part.
+@example
+mysql> select TRUNCATE(1.223,1);
+ -> 1.2
+mysql> select TRUNCATE(1.999,1);
+ -> 1.9
+mysql> select TRUNCATE(1.999,0);
+ -> 1
+@end example
+@end table
+
+@findex String functions
+@findex Functions, string
+@node String functions, Date and time functions, Mathematical functions, Functions
+@subsection String functions
+
+String-valued functions return @code{NULL} if the length of the result would
+be greater than the @code{max_allowed_packet} server parameter. @xref{Server
+parameters}.
+
+For functions that operate on string positions,
+the first position is numbered 1.
+
+@table @code
+@findex ASCII()
+@item ASCII(str)
+Returns the ASCII code value of the leftmost character of the string
+@code{str}. Returns @code{0} if @code{str} is the empty string. Returns
+@code{NULL} if @code{str} is @code{NULL}.
+
+@example
+mysql> select ASCII('2');
+ -> 50
+mysql> select ASCII(2);
+ -> 50
+mysql> select ASCII('dx');
+ -> 100
+@end example
+
+See also the @code{ORD()} function.
+
+@findex ORD()
+@item ORD(str)
+If the leftmost character of the string str is a multi-byte character,
+returns the code of multi-byte character by returning the ASCII code value
+of the character in the format of:
+@code{((first byte ASCII code)*256+(second byte ASCII code))[*256+third byte ASCII code...]}.
+If the leftmost character is not a multi-byte character, returns the same
+value as the like @code{ASCII()} function does.
+
+@example
+mysql> select ORD('2');
+ -> 50
+@end example
+
+@findex CONV()
+@item CONV(N,from_base,to_base)
+Converts numbers between different number bases. Returns a string
+representation of the number @code{N}, converted from base @code{from_base}
+to base @code{to_base}. Returns @code{NULL} if any argument is @code{NULL}.
+The argument @code{N} is interpreted as an integer, but may be specified as
+an integer or a string. The minimum base is @code{2} and the maximum base is
+@code{36}. If @code{to_base} is a negative number, @code{N} is regarded as a
+signed number. Otherwise, @code{N} is treated as unsigned. @code{CONV} works
+with 64-bit precision.
+
+@example
+mysql> select CONV("a",16,2);
+ -> '1010'
+mysql> select CONV("6E",18,8);
+ -> '172'
+mysql> select CONV(-17,10,-18);
+ -> '-H'
+mysql> select CONV(10+"10"+'10'+0xa,10,10);
+ -> '40'
+@end example
+
+@findex BIN()
+@item BIN(N)
+Returns a string representation of the binary value of @code{N}, where
+@code{N} is a longlong (@code{BIGINT}) number. This is equivalent to
+@code{CONV(N,10,2)}. Returns @code{NULL} if @code{N} is @code{NULL}.
+
+@example
+mysql> select BIN(12);
+ -> '1100'
+@end example
+
+@findex OCT()
+@item OCT(N)
+Returns a string representation of the octal value of @code{N}, where
+@code{N} is a longlong number. This is equivalent to @code{CONV(N,10,8)}.
+Returns @code{NULL} if @code{N} is @code{NULL}.
+
+@example
+mysql> select OCT(12);
+ -> '14'
+@end example
+
+@findex HEX()
+@item HEX(N)
+Returns a string representation of the hexadecimal value of @code{N}, where
+@code{N} is a longlong (@code{BIGINT}) number. This is equivalent to
+@code{CONV(N,10,16)}. Returns @code{NULL} if @code{N} is @code{NULL}.
+
+@example
+mysql> select HEX(255);
+ -> 'FF'
+@end example
+
+@findex CHAR()
+@item CHAR(N,...)
+@code{CHAR()} interprets the arguments as integers and returns a string
+consisting of the characters given by the ASCII code values of those
+integers. @code{NULL} values are skipped.
+
+@example
+mysql> select CHAR(77,121,83,81,'76');
+ -> 'MySQL'
+mysql> select CHAR(77,77.3,'77.3');
+ -> 'MMM'
+@end example
+
+@findex CONCAT()
+@item CONCAT(str1,str2,...)
+Returns the string that results from concatenating the arguments. Returns
+@code{NULL} if any argument is @code{NULL}. May have more than 2 arguments.
+A numeric argument is converted to the equivalent string form.
+@example
+mysql> select CONCAT('My', 'S', 'QL');
+ -> 'MySQL'
+mysql> select CONCAT('My', NULL, 'QL');
+ -> NULL
+mysql> select CONCAT(14.3);
+ -> '14.3'
+@end example
+
+@findex CONCAT_WS()
+@item CONCAT_WS(separator, str1, str2,...)
+
+@code{CONCAT_WS()} stands for CONCAT With Separator and is a special form of
+@code{CONCAT()}. The irst argument is the separator for the rest of the
+arguments. The separator can be a string as well as the rest of the
+arguments. If the separator is @code{NULL}, the result will be @code{NULL}.
+The function will skip any @code{NULL}s and empty strings, after the
+separator argument. The separator will be added between the strings to be
+concatenated.
+@example
+mysql> select CONCAT_WS(",","First name","Second name","Last Name");
+ -> 'First name,Second name,Last Name'
+mysql> select CONCAT_WS(",","First name",NULL,"Last Name");
+ -> 'First name,Last Name'
+@end example
+
+@findex LENGTH()
+@findex OCTET_LENGTH()
+@findex CHAR_LENGTH()
+@findex CHARACTER_LENGTH()
+@item LENGTH(str)
+@itemx OCTET_LENGTH(str)
+@itemx CHAR_LENGTH(str)
+@itemx CHARACTER_LENGTH(str)
+Returns the length of the string @code{str}.
+@example
+mysql> select LENGTH('text');
+ -> 4
+mysql> select OCTET_LENGTH('text');
+ -> 4
+@end example
+
+Note that for @code{CHAR_LENGTH()}, multi-byte characters are only counted once.
+
+@findex LOCATE()
+@findex POSITION()
+@item LOCATE(substr,str)
+@itemx POSITION(substr IN str)
+Returns the position of the first occurrence of substring @code{substr}
+in string @code{str}. Returns @code{0} if @code{substr} is not in @code{str}.
+@example
+mysql> select LOCATE('bar', 'foobarbar');
+ -> 4
+mysql> select LOCATE('xbar', 'foobar');
+ -> 0
+@end example
+
+This function is multi-byte safe.
+
+@findex LOCATE()
+@item LOCATE(substr,str,pos)
+Returns the position of the first occurrence of substring @code{substr} in
+string @code{str}, starting at position @code{pos}.
+Returns @code{0} if @code{substr} is not in @code{str}.
+@example
+mysql> select LOCATE('bar', 'foobarbar',5);
+ -> 7
+@end example
+
+This function is multi-byte safe.
+
+@findex INSTR()
+@item INSTR(str,substr)
+Returns the position of the first occurrence of substring @code{substr} in
+string @code{str}. This is the same as the two-argument form of
+@code{LOCATE()}, except that the arguments are swapped.
+
+@example
+mysql> select INSTR('foobarbar', 'bar');
+ -> 4
+mysql> select INSTR('xbar', 'foobar');
+ -> 0
+@end example
+
+This function is multi-byte safe.
+
+@findex LPAD()
+@item LPAD(str,len,padstr)
+Returns the string @code{str}, left-padded with the string
+@code{padstr} until @code{str} is @code{len} characters long.
+@example
+mysql> select LPAD('hi',4,'??');
+ -> '??hi'
+@end example
+
+@findex RPAD()
+@item RPAD(str,len,padstr)
+Returns the string @code{str}, right-padded with the string
+@code{padstr} until @code{str} is @code{len} characters long.
+@example
+mysql> select RPAD('hi',5,'?');
+ -> 'hi???'
+@end example
+
+@findex LEFT()
+@item LEFT(str,len)
+Returns the leftmost @code{len} characters from the string @code{str}.
+@example
+mysql> select LEFT('foobarbar', 5);
+ -> 'fooba'
+@end example
+
+This function is multi-byte safe.
+
+@findex RIGHT()
+@item RIGHT(str,len)
+Returns the rightmost @code{len} characters from the string @code{str}.
+@example
+mysql> select RIGHT('foobarbar', 4);
+ -> 'rbar'
+@end example
+
+This function is multi-byte safe.
+
+@findex SUBSTRING()
+@findex MID()
+@item SUBSTRING(str,pos,len)
+@itemx SUBSTRING(str FROM pos FOR len)
+@itemx MID(str,pos,len)
+Returns a substring @code{len} characters long from string @code{str},
+starting at position @code{pos}.
+The variant form that uses @code{FROM} is ANSI SQL92 syntax.
+@example
+mysql> select SUBSTRING('Quadratically',5,6);
+ -> 'ratica'
+@end example
+
+This function is multi-byte safe.
+
+@findex SUBSTRING()
+@item SUBSTRING(str,pos)
+@item SUBSTRING(str FROM pos)
+Returns a substring from string @code{str} starting at position @code{pos}.
+@example
+mysql> select SUBSTRING('Quadratically',5);
+ -> 'ratically'
+mysql> select SUBSTRING('foobarbar' FROM 4);
+ -> 'barbar'
+@end example
+
+This function is multi-byte safe.
+
+@findex SUBSTRING_INDEX()
+@item SUBSTRING_INDEX(str,delim,count)
+Returns the substring from string @code{str} before @code{count}
+occurrences of the delimiter @code{delim}.
+If @code{count} is positive, everything to the left of the final delimiter
+(counting from the left) is returned.
+If @code{count} is negative, everything to the right of the final delimiter
+(counting from the right) is returned.
+@example
+mysql> select SUBSTRING_INDEX('www.mysql.com', '.', 2);
+ -> 'www.mysql'
+mysql> select SUBSTRING_INDEX('www.mysql.com', '.', -2);
+ -> 'mysql.com'
+@end example
+
+This function is multi-byte safe.
+
+@findex LTRIM()
+@item LTRIM(str)
+Returns the string @code{str} with leading space characters removed.
+@example
+mysql> select LTRIM(' barbar');
+ -> 'barbar'
+@end example
+
+@findex RTRIM()
+@item RTRIM(str)
+Returns the string @code{str} with trailing space characters removed.
+@example
+mysql> select RTRIM('barbar ');
+ -> 'barbar'
+@end example
+
+This function is multi-byte safe.
+
+@findex TRIM()
+@item TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)
+Returns the string @code{str} with all @code{remstr} prefixes and/or suffixes
+removed. If none of the specifiers @code{BOTH}, @code{LEADING} or
+@code{TRAILING} are given, @code{BOTH} is assumed. If @code{remstr} is not
+specified, spaces are removed.
+@example
+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'
+@end example
+
+This function is multi-byte safe.
+
+@findex SOUNDEX()
+@item SOUNDEX(str)
+Returns a soundex string from @code{str}. Two strings that sound ``about the
+same'' should have identical soundex strings. A ``standard'' soundex string
+is 4 characters long, but the @code{SOUNDEX()} function returns an
+arbitrarily long string. You can use @code{SUBSTRING()} on the result to get
+a ``standard'' soundex string. All non-alphanumeric characters are ignored
+in the given string. All international alpha characters outside the A-Z range
+are treated as vowels.
+
+@example
+mysql> select SOUNDEX('Hello');
+ -> 'H400'
+mysql> select SOUNDEX('Quadratically');
+ -> 'Q36324'
+@end example
+
+@findex SPACE()
+@item SPACE(N)
+Returns a string consisting of @code{N} space characters.
+@example
+mysql> select SPACE(6);
+ -> ' '
+@end example
+
+@findex REPLACE()
+@item REPLACE(str,from_str,to_str)
+Returns the string @code{str} with all all occurrences of the string
+@code{from_str} replaced by the string @code{to_str}.
+
+@example
+mysql> select REPLACE('www.mysql.com', 'w', 'Ww');
+ -> 'WwWwWw.mysql.com'
+@end example
+
+This function is multi-byte safe.
+
+@findex REPEAT()
+@item REPEAT(str,count)
+Returns a string consisting of the string @code{str} repeated @code{count}
+times. If @code{count <= 0}, returns an empty string. Returns @code{NULL} if
+@code{str} or @code{count} are @code{NULL}.
+
+@example
+mysql> select REPEAT('MySQL', 3);
+ -> 'MySQLMySQLMySQL'
+@end example
+
+@findex REVERSE()
+@item REVERSE(str)
+Returns the string @code{str} with the order of the characters reversed.
+@example
+mysql> select REVERSE('abc');
+ -> 'cba'
+@end example
+
+This function is multi-byte safe.
+
+@findex INSERT()
+@item INSERT(str,pos,len,newstr)
+Returns the string @code{str}, with the substring beginning at position
+@code{pos} and @code{len} characters long replaced by the string
+@code{newstr}.
+
+@example
+mysql> select INSERT('Quadratic', 3, 4, 'What');
+ -> 'QuWhattic'
+@end example
+
+This function is multi-byte safe.
+
+@findex ELT()
+@item ELT(N,str1,str2,str3,...)
+Returns @code{str1} if @code{N} = @code{1}, @code{str2} if @code{N} =
+@code{2}, and so on. Returns @code{NULL} if @code{N} is less than @code{1}
+or greater than the number of arguments. @code{ELT()} is the complement of
+@code{FIELD()}.
+
+@example
+mysql> select ELT(1, 'ej', 'Heja', 'hej', 'foo');
+ -> 'ej'
+mysql> select ELT(4, 'ej', 'Heja', 'hej', 'foo');
+ -> 'foo'
+@end example
+
+@findex FIELD()
+@item FIELD(str,str1,str2,str3,...)
+Returns the index of @code{str} in the @code{str1}, @code{str2},
+@code{str3}, @code{...} list.
+Returns @code{0} if @code{str} is not found.
+@code{FIELD()} is the complement of @code{ELT()}.
+
+@example
+mysql> select FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');
+ -> 2
+mysql> select FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');
+ -> 0
+@end example
+
+@findex FIND_IN_SET()
+@item FIND_IN_SET(str,strlist)
+Returns a value @code{1} to @code{N} if the string @code{str} is in the list
+@code{strlist} consisting of @code{N} substrings. A string list is a string
+composed of substrings separated by @samp{,} characters. If the first
+argument is a constant string and the second is a column of type @code{SET},
+the @code{FIND_IN_SET()} function is optimized to use bit arithmetic!
+Returns @code{0} if @code{str} is not in @code{strlist} or if @code{strlist}
+is the empty string. Returns @code{NULL} if either argument is @code{NULL}.
+This function will not work properly if the first argument contains a
+@samp{,}.
+
+@example
+mysql> SELECT FIND_IN_SET('b','a,b,c,d');
+ -> 2
+@end example
+
+@findex MAKE_SET()
+@item MAKE_SET(bits,str1,str2,...)
+Returns a set (a string containing substrings separated by @samp{,}
+characters) consisting of the strings that have the corresponding bit in
+@code{bits} set. @code{str1} corresponds to bit 0, @code{str2} to bit 1,
+etc. @code{NULL} strings in @code{str1}, @code{str2}, @code{...}
+are not appended to the result.
+
+@example
+mysql> SELECT MAKE_SET(1,'a','b','c');
+ -> 'a'
+mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world');
+ -> 'hello,world'
+mysql> SELECT MAKE_SET(0,'a','b','c');
+ -> ''
+@end example
+
+@findex EXPORT_SET()
+@item EXPORT_SET(bits,on,off,[separator,[number_of_bits]])
+Returns a string where for every bit set in 'bit', you get a 'on' string and for
+every reset bit you get an 'off' string. Each string is separated with 'separator'
+(default ',') and only 'number_of_bits' (default 64) of 'bits' is used.
+
+@example
+mysql> select EXPORT_SET(5,'Y','N',',',4)
+ -> Y,N,Y,N
+@end example
+
+@findex LCASE()
+@findex LOWER()
+@item LCASE(str)
+@itemx LOWER(str)
+Returns the string @code{str} with all characters changed to lowercase
+according to the current character set mapping (the default is ISO-8859-1
+Latin1).
+
+This function is multi-byte safe.
+
+@example
+mysql> select LCASE('QUADRATICALLY');
+ -> 'quadratically'
+@end example
+
+@findex UCASE()
+@findex UPPER()
+@item UCASE(str)
+@itemx UPPER(str)
+Returns the string @code{str} with all characters changed to uppercase
+according to the current character set mapping (the default is ISO-8859-1
+Latin1).
+
+@example
+mysql> select UCASE('Hej');
+ -> 'HEJ'
+@end example
+
+This function is multi-byte safe.
+
+@findex FILE
+@item LOAD_FILE(file_name)
+Reads the file and returns the file contents as a string. The file
+must be on the server, you must specify the full pathname to the
+file, and you must have the @strong{file} privilege. The file must
+be readable by all and be smaller than @code{max_allowed_packet}.
+
+If the file doesn't exist or can't be read due to one of the above reasons,
+the function returns @code{NULL}.
+
+@example
+mysql> UPDATE table_name
+ SET blob_column=LOAD_FILE("/tmp/picture")
+ WHERE id=1;
+@end example
+@end table
+
+If you are not using @strong{MySQL 3.23}, you have to do the reading of
+the file inside your application and create an @code{INSERT} statement
+to update the database with the file information. One way to do this, if
+you are using the @strong{MySQL}++ library, can be found at
+@uref{http://www.mysql.com/documentation/mysql++/mysql++-examples.html}.
+
+@strong{MySQL} automatically converts numbers to strings as necessary, and
+vice versa:
+
+@example
+mysql> SELECT 1+"1";
+ -> 2
+mysql> SELECT CONCAT(2,' test');
+ -> '2 test'
+@end example
+
+If you want to convert a number to a string explicitly, pass it as the
+argument to @code{CONCAT()}.
+
+If a string function is given a binary string as an argument, the resulting
+string is also a binary string. A number converted to a string is treated as
+a binary string. This only affects comparisons.
+
+@findex Date and time functions
+@findex Functions, date and time
+@node Date and time functions, Miscellaneous functions, String functions, Functions
+@subsection Date and time functions
+
+See @ref{Date and time types} for a description of the range of values
+each type has, and the valid formats in which date and time values may be
+specified.
+
+Here is an example that uses date functions. The query below selects
+all records with a @code{date_col} value from within the last 30 days:
+
+@example
+mysql> SELECT something FROM table
+ WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30;
+@end example
+
+@table @code
+@findex DAYOFWEEK()
+@item DAYOFWEEK(date)
+Returns the weekday index
+for @code{date} (@code{1} = Sunday, @code{2} = Monday, ... @code{7} = Saturday).
+These index values correspond to the ODBC standard.
+@example
+mysql> select DAYOFWEEK('1998-02-03');
+ -> 3
+@end example
+
+@findex WEEKDAY()
+@item WEEKDAY(date)
+Returns the weekday index for
+@code{date} (@code{0} = Monday, @code{1} = Tuesday, ... @code{6} = Sunday).
+@example
+mysql> select WEEKDAY('1997-10-04 22:23:00');
+ -> 5
+mysql> select WEEKDAY('1997-11-05');
+ -> 2
+@end example
+
+@findex DAYOFMONTH()
+@item DAYOFMONTH(date)
+Returns the day of the month for @code{date}, in the range @code{1} to
+@code{31}.
+@example
+mysql> select DAYOFMONTH('1998-02-03');
+ -> 3
+@end example
+
+@findex DAYOFYEAR()
+@item DAYOFYEAR(date)
+Returns the day of the year for @code{date}, in the range @code{1} to
+@code{366}.
+@example
+mysql> select DAYOFYEAR('1998-02-03');
+ -> 34
+@end example
+
+@findex MONTH()
+@item MONTH(date)
+Returns the month for @code{date}, in the range @code{1} to @code{12}.
+@example
+mysql> select MONTH('1998-02-03');
+ -> 2
+@end example
+
+@findex DAYNAME()
+@item DAYNAME(date)
+Returns the name of the weekday for @code{date}.
+@example
+mysql> select DAYNAME("1998-02-05");
+ -> 'Thursday'
+@end example
+
+@findex MONTHNAME()
+@item MONTHNAME(date)
+Returns the name of the month for @code{date}.
+@example
+mysql> select MONTHNAME("1998-02-05");
+ -> 'February'
+@end example
+
+@findex QUARTER()
+@item QUARTER(date)
+Returns the quarter of the year for @code{date}, in the range @code{1}
+to @code{4}.
+@example
+mysql> select QUARTER('98-04-01');
+ -> 2
+@end example
+
+@findex WEEK()
+@item WEEK(date)
+@itemx WEEK(date,first)
+With a single argument, returns the week for @code{date}, in the range
+@code{0} to @code{53} (yes, there may be the beginnings of a week 53),
+for locations where Sunday is the first day of the week. The
+two-argument form of @code{WEEK()} allows you to specify whether the
+week starts on Sunday or Monday. The week starts on Sunday if the
+second argument is @code{0}, on Monday if the second argument is
+@code{1}.
+@example
+mysql> select WEEK('1998-02-20');
+ -> 7
+mysql> select WEEK('1998-02-20',0);
+ -> 7
+mysql> select WEEK('1998-02-20',1);
+ -> 8
+mysql> select WEEK('1998-12-31',1);
+ -> 53
+@end example
+
+@findex YEAR()
+@item YEAR(date)
+Returns the year for @code{date}, in the range @code{1000} to @code{9999}.
+@example
+mysql> select YEAR('98-02-03');
+ -> 1998
+@end example
+
+@item YEARWEEK(date)
+@itemx YEARWEEK(date,first)
+Returns year and week for a date. The second arguments works exactly
+like the second argument to @code{WEEK()}. Note that the year may be
+different from the year in the date argument for the first and the last
+week of the year!
+@example
+mysql> select YEARWEEK('1987-01-01');
+ -> 198653
+@end example
+
+@findex HOUR()
+@item HOUR(time)
+Returns the hour for @code{time}, in the range @code{0} to @code{23}.
+@example
+mysql> select HOUR('10:05:03');
+ -> 10
+@end example
+
+@findex MINUTE()
+@item MINUTE(time)
+Returns the minute for @code{time}, in the range @code{0} to @code{59}.
+@example
+mysql> select MINUTE('98-02-03 10:05:03');
+ -> 5
+@end example
+
+@findex SECOND()
+@item SECOND(time)
+Returns the second for @code{time}, in the range @code{0} to @code{59}.
+@example
+mysql> select SECOND('10:05:03');
+ -> 3
+@end example
+
+@findex PERIOD_ADD()
+@item PERIOD_ADD(P,N)
+Adds @code{N} months to period @code{P} (in the format @code{YYMM} or
+@code{YYYYMM}). Returns a value in the format @code{YYYYMM}.
+
+Note that the period argument @code{P} is @emph{not} a date value.
+
+@example
+mysql> select PERIOD_ADD(9801,2);
+ -> 199803
+@end example
+
+@findex PERIOD_DIFF()
+@item PERIOD_DIFF(P1,P2)
+Returns the number of months between periods @code{P1} and @code{P2}.
+@code{P1} and @code{P2} should be in the format @code{YYMM} or @code{YYYYMM}.
+
+Note that the period arguments @code{P1} and @code{P2} are @emph{not}
+date values.
+
+@example
+mysql> select PERIOD_DIFF(9802,199703);
+ -> 11
+@end example
+
+@findex DATE_ADD()
+@findex DATE_SUB()
+@findex ADDDATE()
+@findex SUBDATE()
+@findex EXTRACT(type FROM date)
+@item DATE_ADD(date,INTERVAL expr type)
+@itemx DATE_SUB(date,INTERVAL expr type)
+@itemx ADDDATE(date,INTERVAL expr type)
+@itemx SUBDATE(date,INTERVAL expr type)
+
+These functions perform date arithmetic. They are new for @strong{MySQL}
+3.22. @code{ADDDATE()} and @code{SUBDATE()} are synonyms for
+@code{DATE_ADD()} and @code{DATE_SUB()}.
+
+In @strong{MySQL} 3.23, you can use @code{+} and @code{-} instead of
+@code{DATE_ADD()} and @code{DATE_SUB()}. (See example)
+
+@code{date} is a @code{DATETIME} or @code{DATE} value specifying the starting
+date. @code{expr} is an expression specifying the interval value to be added
+or substracted from the starting date. @code{expr} is a string; it may start
+with a @samp{-} for negative intervals. @code{type} is a keyword indicating
+how the expression should be interpreted.
+
+The @code{EXTRACT(type FROM date)} function returns the 'type'
+interval from the date.
+
+The following table shows how the @code{type} and @code{expr} arguments
+are related:
+
+@multitable @columnfractions .18 .3 .42
+@item @code{type} @strong{value} @tab @strong{Meaning} @tab @strong{Expected} @code{expr} @strong{format}
+@item @code{SECOND} @tab Seconds @tab @code{SECONDS}
+@item @code{MINUTE} @tab Minutes @tab @code{MINUTES}
+@item @code{HOUR} @tab Hours @tab @code{HOURS}
+@item @code{DAY} @tab Days @tab @code{DAYS}
+@item @code{MONTH} @tab Months @tab @code{MONTHS}
+@item @code{YEAR} @tab Years @tab @code{YEARS}
+@item @code{MINUTE_SECOND} @tab Minutes and seconds @tab @code{"MINUTES:SECONDS"}
+@item @code{HOUR_MINUTE} @tab Hours and minutes @tab @code{"HOURS:MINUTES"}
+@item @code{DAY_HOUR} @tab Days and hours @tab @code{"DAYS HOURS"}
+@item @code{YEAR_MONTH} @tab Years and months @tab @code{"YEARS-MONTHS"}
+@item @code{HOUR_SECOND} @tab Hours, minutes, @tab @code{"HOURS:MINUTES:SECONDS"}
+@item @code{DAY_MINUTE} @tab Days, hours, minutes @tab @code{"DAYS HOURS:MINUTES"}
+@item @code{DAY_SECOND} @tab Days, hours, minutes, seconds @tab @code{"DAYS HOURS:MINUTES:SECONDS"}
+@end multitable
+
+@strong{MySQL} allows any punctuation delimiter in the @code{expr} format.
+The ones shown in the table are the suggested delimiters. If the @code{date}
+argument is a @code{DATE} value and your calculations involve only
+@code{YEAR}, @code{MONTH} and @code{DAY} parts (that is, no time parts), the
+result is a @code{DATE} value. Otherwise the result is a @code{DATETIME}
+value.
+
+@example
+mysql> SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND;
+ -> 1998-01-01 00:00:00
+mysql> SELECT INTERVAL 1 DAY + "1997-12-31";
+ -> 1998-01-01
+mysql> SELECT "1998-01-01" - INTERVAL 1 SECOND;
+ -> 1997-12-31 23:59:59
+mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
+ INTERVAL 1 SECOND);
+ -> 1998-01-01 00:00:00
+mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
+ INTERVAL 1 DAY);
+ -> 1998-01-01 23:59:59
+mysql> SELECT DATE_ADD("1997-12-31 23:59:59",
+ INTERVAL "1:1" MINUTE_SECOND);
+ -> 1998-01-01 00:01:00
+mysql> SELECT DATE_SUB("1998-01-01 00:00:00",
+ INTERVAL "1 1:1:1" DAY_SECOND);
+ -> 1997-12-30 22:58:59
+mysql> SELECT DATE_ADD("1998-01-01 00:00:00",
+ INTERVAL "-1 10" DAY_HOUR);
+ -> 1997-12-30 14:00:00
+mysql> SELECT DATE_SUB("1998-01-02", INTERVAL 31 DAY);
+ -> 1997-12-02
+mysql> SELECT EXTRACT(YEAR FROM "1999-07-02");
+ -> 1999
+mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03");
+ -> 199907
+mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03");
+ -> 20102
+@end example
+
+If you specify an interval value that is too short (does not include all the
+interval parts that would be expected from the @code{type} keyword),
+@strong{MySQL} assumes you have left out the leftmost parts of the interval
+value. For example, if you specify a @code{type} of @code{DAY_SECOND}, the
+value of @code{expr} is expected to have days, hours, minutes and seconds
+parts. If you specify a value like @code{"1:10"}, @strong{MySQL} assumes
+that the days and hours parts are missing and the value represents minutes
+and seconds. In other words, @code{"1:10" DAY_SECOND} is interpreted in such
+a way that it is equivalent to @code{"1:10" MINUTE_SECOND}. This is
+analogous to the way that @strong{MySQL} interprets @code{TIME} values
+as representing elapsed time rather than as time of day.
+
+If you use really incorrect dates, the result is @code{NULL}. If you add
+@code{MONTH}, @code{YEAR_MONTH} or @code{YEAR} and the resulting date
+has a day that is larger than the maximum day for the new month, the day is
+adjusted to the maximum days in the new month.
+
+@example
+mysql> select DATE_ADD('1998-01-30', Interval 1 month);
+ -> 1998-02-28
+@end example
+
+Note from the preceding example that the word @code{INTERVAL} and the
+@code{type} keyword are not case sensitive.
+
+@findex TO_DAYS()
+@item TO_DAYS(date)
+Given a date @code{date}, returns a daynumber (the number of days since year
+0).
+
+@example
+mysql> select TO_DAYS(950501);
+ -> 728779
+mysql> select TO_DAYS('1997-10-07');
+ -> 729669
+@end example
+
+@code{TO_DAYS()} is not intended for use with values that precede the advent
+of the Gregorian calendar (1582), because it doesn't take into account the
+days that were lost when the calender was changed.
+
+@findex FROM_DAYS()
+@item FROM_DAYS(N)
+Given a daynumber @code{N}, returns a @code{DATE} value.
+
+@example
+mysql> select FROM_DAYS(729669);
+ -> '1997-10-07'
+@end example
+
+@code{FROM_DAYS()} is not intended for use with values that precede the
+advent of the Gregorian calendar (1582), because it doesn't take into account
+the days that were lost when the calender was changed.
+
+@findex DATE_FORMAT()
+@item DATE_FORMAT(date,format)
+Formats the @code{date} value according to the @code{format} string. The
+following specifiers may be used in the @code{format} string:
+@multitable @columnfractions .1 .9
+@item @code{%M} @tab Month name (@code{January}..@code{December})
+@item @code{%W} @tab Weekday name (@code{Sunday}..@code{Saturday})
+@item @code{%D} @tab Day of the month with english suffix (@code{1st}, @code{2nd}, @code{3rd}, etc.)
+@item @code{%Y} @tab Year, numeric, 4 digits
+@item @code{%y} @tab Year, numeric, 2 digits
+@item @code{%X} @tab Year for the week where Sunday is the first day of the week, numeric, 4 digits, used with '%V'
+@item @code{%x} @tab Year for the week, where Monday is the first day of the week, numeric, 4 digits, used with '%v'
+@item @code{%a} @tab Abbreviated weekday name (@code{Sun}..@code{Sat})
+@item @code{%d} @tab Day of the month, numeric (@code{00}..@code{31})
+@item @code{%e} @tab Day of the month, numeric (@code{0}..@code{31})
+@item @code{%m} @tab Month, numeric (@code{01}..@code{12})
+@item @code{%c} @tab Month, numeric (@code{1}..@code{12})
+@item @code{%b} @tab Abbreviated month name (@code{Jan}..@code{Dec})
+@item @code{%j} @tab Day of year (@code{001}..@code{366})
+@item @code{%H} @tab Hour (@code{00}..@code{23})
+@item @code{%k} @tab Hour (@code{0}..@code{23})
+@item @code{%h} @tab Hour (@code{01}..@code{12})
+@item @code{%I} @tab Hour (@code{01}..@code{12})
+@item @code{%l} @tab Hour (@code{1}..@code{12})
+@item @code{%i} @tab Minutes, numeric (@code{00}..@code{59})
+@item @code{%r} @tab Time, 12-hour (@code{hh:mm:ss [AP]M})
+@item @code{%T} @tab Time, 24-hour (@code{hh:mm:ss})
+@item @code{%S} @tab Seconds (@code{00}..@code{59})
+@item @code{%s} @tab Seconds (@code{00}..@code{59})
+@item @code{%p} @tab @code{AM} or @code{PM}
+@item @code{%w} @tab Day of the week (@code{0}=Sunday..@code{6}=Saturday)
+@item @code{%U} @tab Week (@code{0}..@code{53}), where Sunday is the first day of the week
+@item @code{%u} @tab Week (@code{0}..@code{53}), where Monday is the first day of the week
+@item @code{%V} @tab Week (@code{1}..@code{53}), where Sunday is the first day of the week. Used with '%X'
+@item @code{%v} @tab Week (@code{1}..@code{53}), where Monday is the first day of the week. Used with '%x'
+@item @code{%%} @tab A literal @samp{%}.
+@end multitable
+
+All other characters are just copied to the result without interpretation.
+
+@example
+mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');
+ -> 'Saturday October 1997'
+mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');
+ -> '22:23:00'
+mysql> select DATE_FORMAT('1997-10-04 22:23:00',
+ '%D %y %a %d %m %b %j');
+ -> '4th 97 Sat 04 10 Oct 277'
+mysql> select DATE_FORMAT('1997-10-04 22:23:00',
+ '%H %k %I %r %T %S %w');
+ -> '22 22 10 10:23:00 PM 22:23:00 00 6'
+mysql> select DATE_FORMAT('1999-01-01', '%X %V');
+ -> '1998 52'
+@end example
+
+As of @strong{MySQL} 3.23, the @code{%} character is required before
+format specifier characters. In earlier versions of @strong{MySQL},
+@code{%} was optional.
+
+@findex TIME_FORMAT()
+@item TIME_FORMAT(time,format)
+This is used like the @code{DATE_FORMAT()} function above, but the
+@code{format} string may contain only those format specifiers that handle
+hours, minutes and seconds. Other specifiers produce a @code{NULL} value or
+@code{0}.
+
+@findex CURDATE()
+@findex CURRENT_DATE
+@item CURDATE()
+@itemx CURRENT_DATE
+Returns today's date as a value in @code{'YYYY-MM-DD'} or @code{YYYYMMDD}
+format, depending on whether the function is used in a string or numeric
+context.
+
+@example
+mysql> select CURDATE();
+ -> '1997-12-15'
+mysql> select CURDATE() + 0;
+ -> 19971215
+@end example
+
+@findex CURTIME()
+@findex CURRENT_TIME
+@item CURTIME()
+@itemx CURRENT_TIME
+Returns the current time as a value in @code{'HH:MM:SS'} or @code{HHMMSS}
+format, depending on whether the function is used in a string or numeric
+context.
+
+@example
+mysql> select CURTIME();
+ -> '23:50:26'
+mysql> select CURTIME() + 0;
+ -> 235026
+@end example
+
+@findex NOW()
+@findex SYSDATE()
+@findex CURRENT_TIMESTAMP
+@item NOW()
+@itemx SYSDATE()
+@itemx CURRENT_TIMESTAMP
+Returns the current date and time as a value in @code{'YYYY-MM-DD HH:MM:SS'}
+or @code{YYYYMMDDHHMMSS} format, depending on whether the function is used in
+a string or numeric context.
+
+@example
+mysql> select NOW();
+ -> '1997-12-15 23:50:26'
+mysql> select NOW() + 0;
+ -> 19971215235026
+@end example
+
+@findex UNIX_TIMESTAMP()
+@item UNIX_TIMESTAMP()
+@itemx UNIX_TIMESTAMP(date)
+If called with no argument, returns a Unix timestamp (seconds since
+@code{'1970-01-01 00:00:00'} GMT). If @code{UNIX_TIMESTAMP()} is called with
+a @code{date} argument, it returns the value of the argument as seconds since
+@code{'1970-01-01 00:00:00'} GMT. @code{date} may be a @code{DATE} string,
+a @code{DATETIME} string, a @code{TIMESTAMP}, or a number in the format
+@code{YYMMDD} or @code{YYYYMMDD} in local time.
+
+@example
+mysql> select UNIX_TIMESTAMP();
+ -> 882226357
+mysql> select UNIX_TIMESTAMP('1997-10-04 22:23:00');
+ -> 875996580
+@end example
+
+When @code{UNIX_TIMESTAMP} is used on a @code{TIMESTAMP} column, the function
+will receive the value directly, with no implicit
+``string-to-unix-timestamp'' conversion.
+If you give @code{UNIX_TIMESTAMP()} a wrong or out-of-range date, it will
+return 0.
+
+@findex FROM_UNIXTIME()
+@item FROM_UNIXTIME(unix_timestamp)
+Returns a representation of the @code{unix_timestamp} argument as a value in
+@code{'YYYY-MM-DD HH:MM:SS'} or @code{YYYYMMDDHHMMSS} format, depending on
+whether the function is used in a string or numeric context.
+
+@example
+mysql> select FROM_UNIXTIME(875996580);
+ -> '1997-10-04 22:23:00'
+mysql> select FROM_UNIXTIME(875996580) + 0;
+ -> 19971004222300
+@end example
+
+@findex FROM_UNIXTIME()
+@item FROM_UNIXTIME(unix_timestamp,format)
+Returns a string representation of the Unix timestamp, formatted according to
+the @code{format} string. @code{format} may contain the same specifiers as
+those listed in the entry for the @code{DATE_FORMAT()} function.
+
+@example
+mysql> select FROM_UNIXTIME(UNIX_TIMESTAMP(),
+ '%Y %D %M %h:%i:%s %x');
+ -> '1997 23rd December 03:43:30 x'
+@end example
+
+@findex SEC_TO_TIME()
+@item SEC_TO_TIME(seconds)
+Returns the @code{seconds} argument, converted to hours, minutes and seconds,
+as a value in @code{'HH:MM:SS'} or @code{HHMMSS} format, depending on whether
+the function is used in a string or numeric context.
+
+@example
+mysql> select SEC_TO_TIME(2378);
+ -> '00:39:38'
+mysql> select SEC_TO_TIME(2378) + 0;
+ -> 3938
+@end example
+
+@findex TIME_TO_SEC()
+@item TIME_TO_SEC(time)
+Returns the @code{time} argument, converted to seconds.
+@example
+mysql> select TIME_TO_SEC('22:23:00');
+ -> 80580
+mysql> select TIME_TO_SEC('00:39:38');
+ -> 2378
+@end example
+@end table
+
+@findex Miscellaneous functions
+@findex Functions, miscellaneous
+@node Miscellaneous functions, Group by functions, Date and time functions, Functions
+@subsection Miscellaneous functions
+
+@table @code
+@findex DATABASE()
+@item DATABASE()
+Returns the current database name.
+@example
+mysql> select DATABASE();
+ -> 'test'
+@end example
+
+If there is no current database, @code{DATABASE()} returns the empty string.
+
+@findex USER()
+@findex SYSTEM_USER()
+@findex SESSION_USER()
+@item USER()
+@itemx SYSTEM_USER()
+@itemx SESSION_USER()
+Returns the current @strong{MySQL} user name.
+@example
+mysql> select USER();
+ -> 'davida@@localhost'
+@end example
+
+In @strong{MySQL} 3.22.11 or later, this includes the client hostname as well as the
+user name. You can extract just the user name part like this (which works
+whether or not the value includes a hostname part):
+
+@example
+mysql> select substring_index(USER(),"@@",1);
+ -> 'davida'
+@end example
+
+@findex PASSWORD()
+@item PASSWORD(str)
+Calculates a password string from the plaintext password @code{str}. This is
+the function that is used for encrypting @strong{MySQL} passwords for storage
+in the @code{Password} column of the @code{user} grant table.
+
+@example
+mysql> select PASSWORD('badpwd');
+ -> '7f84554057dd964b'
+@end example
+
+@cindex Password encryption, reversibility of
+@code{PASSWORD()} encryption is non-reversible.
+
+@code{PASSWORD()} does not perform password encryption in the same way that
+Unix passwords are encrypted. You should not assume that if your Unix
+password and your @strong{MySQL} password are the same, @code{PASSWORD()}
+will result in the same encrypted value as is stored in the Unix password
+file. See @code{ENCRYPT()}.
+
+@findex ENCRYPT()
+@item ENCRYPT(str[,salt])
+Encrypt @code{str} using the Unix @code{crypt()} system call. The
+@code{salt} argument should be a string with two characters.
+(As of @strong{MySQL} 3.22.16, @code{salt} may be longer than two characters.)
+
+@example
+mysql> select ENCRYPT("hello");
+ -> 'VxuFAJXVARROc'
+@end example
+
+If @code{crypt()} is not available on your system, @code{ENCRYPT()} always
+returns @code{NULL}.
+
+@code{ENCRYPT()} ignores all but the first 8 characters of @code{str}, at
+least on some systems. This will be determined by the behavior of the
+underlying @code{crypt()} system call.
+
+@findex ENCODE()
+@item ENCODE(str,pass_str)
+Encrypt @code{str} using @code{pass_str} as the password.
+To decrypt the result, use @code{DECODE()}.
+
+The results is a binary string of the same length as @code{string}.
+If you want to save it in a column, use a @code{BLOB} column type.
+
+@findex DECODE()
+@item DECODE(crypt_str,pass_str)
+Descrypts the encrypted string @code{crypt_str} using @code{pass_str} as the
+password. @code{crypt_str} should be a string returned from
+@code{ENCODE()}.
+
+@findex MD5()
+@item MD5(string)
+Calculates a MD5 checksum for the string. Value is returned as a 32 long
+hex number that may, for example, be used as a hash key.
+
+@example
+mysql> select MD5("testing")
+ -> 'ae2b1fca515949e5d54fb22b8ed95575'
+@end example
+
+This is an "RSA Data Security, Inc. MD5 Message-Digest Algorithm".
+
+@findex LAST_INSERT_ID([expr])
+@item LAST_INSERT_ID([expr])
+Returns the last automatically generated value that was inserted into an
+@code{AUTO_INCREMENT} column.
+@xref{mysql_insert_id,, @code{mysql_insert_id()}}.
+
+@example
+mysql> select LAST_INSERT_ID();
+ -> 195
+@end example
+
+The last ID that was generated is maintained in the server on a
+per-connection basis. It will not be changed by another client. It will not
+even be changed if you update another @code{AUTO_INCREMENT} column with a
+non-magic value (that is, a value that is not @code{NULL} and not @code{0}).
+
+@cindex Sequence emulation
+If @code{expr} is given as an argument to @code{LAST_INSERT_ID()} in an
+@code{UPDATE} clause, then the value of the argument is returned as a
+@code{LAST_INSERT_ID()} value. This can be used to simulate sequences:
+
+First create the table:
+
+@example
+mysql> create table sequence (id int not null);
+mysql> insert into sequence values (0);
+@end example
+
+Then the table can be used to generate sequence numbers like this:
+
+@example
+mysql> update sequence set id=LAST_INSERT_ID(id+1);
+@end example
+
+You can generate sequences without calling @code{LAST_INSERT_ID()}, but the
+utility of using the function this way is that the ID value is maintained in
+the server as the last automatically generated value. You can retrieve the
+new ID as you would read any normal @code{AUTO_INCREMENT} value in
+@strong{MySQL}. For example, @code{LAST_INSERT_ID()} (without an argument)
+will return the new ID. The C API function @code{mysql_insert_id()}
+can also be used to get the value.
+
+@findex FORMAT()
+@item FORMAT(X,D)
+Formats the number @code{X} to a format like @code{'#,###,###.##'}, rounded
+to @code{D} decimals. If @code{D} is @code{0}, the result will have no
+decimal point or fractional part.
+
+@example
+mysql> select FORMAT(12332.123456, 4);
+ -> '12,332.1235'
+mysql> select FORMAT(12332.1,4);
+ -> '12,332.1000'
+mysql> select FORMAT(12332.2,0);
+ -> '12,332'
+@end example
+
+@findex VERSION()
+@item VERSION()
+Returns a string indicating the @strong{MySQL} server version.
+@example
+mysql> select VERSION();
+ -> '3.23.13-log'
+@end example
+
+Note that if your version ends with @code{-log} this means that logging is
+enabled.
+
+@findex CONNECTION_ID()
+@item CONNECTION_ID()
+Returns the connection id (@code{thread_id}) for the connection.
+Every connection has its own unique id.
+@example
+mysql> select CONNECTION_ID();
+ -> 1
+@end example
+
+@findex GET_LOCK()
+@item GET_LOCK(str,timeout)
+Tries to obtain a lock with a name given by the string @code{str}, with a
+timeout of @code{timeout} seconds. Returns @code{1} if the lock was obtained
+successfully, @code{0} if the attempt timed out, or @code{NULL} if an error
+occurred (such as running out of memory or the thread was killed with
+@code{mysqladmin kill}). A lock is released when you execute
+@code{RELEASE_LOCK()}, execute a new @code{GET_LOCK()} or the thread
+terminates. This function can be used to implement application locks or to
+simulate record locks. It blocks requests by other clients for locks with
+the same name; clients that agree on a given lock string name can use the
+string to perform cooperative advisory locking.
+
+@example
+mysql> select GET_LOCK("lock1",10);
+ -> 1
+mysql> select GET_LOCK("lock2",10);
+ -> 1
+mysql> select RELEASE_LOCK("lock2");
+ -> 1
+mysql> select RELEASE_LOCK("lock1");
+ -> NULL
+@end example
+
+Note that the second @code{RELEASE_LOCK()} call returns @code{NULL} because
+the lock @code{"lock1"} was automatically released by the second
+@code{GET_LOCK()} call.
+
+@findex RELEASE_LOCK()
+@item RELEASE_LOCK(str)
+Releases the lock named by the string @code{str} that was obtained with
+@code{GET_LOCK()}. Returns @code{1} if the lock was released, @code{0} if the
+lock wasn't locked by this thread (in which case the lock is not released)
+and @code{NULL} if the named lock didn't exist. The lock will not exist if
+it was never obtained by a call to @code{GET_LOCK()} or if it already has
+been released.
+
+@findex BENCHMARK()
+@item BENCHMARK(count,expr)
+The @code{BENCHMARK()} function executes the expression @code{expr}
+repeatedly @code{count} times. It may be used to time how fast @strong{MySQL}
+processes the expression. The result value is always @code{0}. The intended
+use is in the @code{mysql} client, which reports query execution times.
+
+@example
+mysql> select BENCHMARK(1000000,encode("hello","goodbye"));
++----------------------------------------------+
+| BENCHMARK(1000000,encode("hello","goodbye")) |
++----------------------------------------------+
+| 0 |
++----------------------------------------------+
+1 row in set (4.74 sec)
+@end example
+
+The time reported is elapsed time on the client end, not CPU time on the
+server end. It may be advisable to execute @code{BENCHMARK()} several
+times, and interpret the result with regard to how heavily loaded the
+server machine is.
+
+@findex INET_NTOA()
+@item INET_NTOA(expr)
+Returns the network address (4 or 8 byte) for the numeric expression.
+
+@example
+mysql> select INET_NTOA(3520061480);
+ -> "209.207.224.40"
+@end example
+
+@findex INET_ATON()
+@item INET_ATON(expr)
+Returns an integer that represents the numeric value for a network address
+Addresses may be 4 or 8 byte addresses.
+
+@example
+mysql> select INET_ATON("209.207.224.40");
+ -> 3520061480
+@end example
+@end table
+
+@findex GROUP BY functions
+@findex Functions, GROUP BY
+@node Group by functions, , Miscellaneous functions, Functions
+@subsection Functions for use with @code{GROUP BY} clauses
+
+If you use a group function in a statement containing no @code{GROUP BY}
+clause, it is equivalent to grouping on all rows.
+
+@table @code
+@findex COUNT()
+@item COUNT(expr)
+Returns a count of the number of non-@code{NULL} values in the rows
+retrieved by a @code{SELECT} statement.
+
+@example
+mysql> select student.student_name,COUNT(*)
+ from student,course
+ where student.student_id=course.student_id
+ GROUP BY student_name;
+
+@end example
+
+@code{COUNT(*)} is somewhat different in that it returns a count of
+the number of rows retrieved, whether or not they contain @code{NULL}
+values.
+
+@code{COUNT(*)} is optimized to
+return very quickly if the @code{SELECT} retrieves from one table, no
+other columns are retrieved and there is no @code{WHERE} clause.
+For example:
+
+@example
+mysql> select COUNT(*) from student;
+@end example
+
+@findex COUNT(DISTINCT)
+@findex DISTINCT
+@item COUNT(DISTINCT expr,[expr...])
+Returns a count of the number of different values.
+
+@example
+mysql> select COUNT(DISTINCT results) from student;
+@end example
+
+In @strong{MySQL} you can get the number of distinct expressions combinations
+by giving a list of expressions. In ANSI SQL you would have to do a
+concatenation of all expressions inside @code{CODE(DISTINCT ..)}.
+
+@findex AVG()
+@item AVG(expr)
+Returns the average value of @code{expr}.
+
+@example
+mysql> select student_name, AVG(test_score)
+ from student
+ GROUP BY student_name;
+@end example
+
+@findex MIN()
+@findex MAX()
+@item MIN(expr)
+@itemx MAX(expr)
+Returns the minimum or maximum value of @code{expr}. @code{MIN()} and
+@code{MAX()} may take a string argument; in such cases they return the
+minimum or maximum string value.
+
+@example
+mysql> select student_name, MIN(test_score), MAX(test_score)
+ from student
+ GROUP BY student_name;
+@end example
+
+@findex SUM()
+@item SUM(expr)
+Returns the sum of @code{expr}. Note that if the return set has no rows,
+it returns NULL!
+
+@findex STD()
+@findex STDDEV()
+@cindex Oracle compatibility
+@cindex Compatibility, with Oracle
+@item STD(expr)
+@itemx STDDEV(expr)
+Returns the standard deviation of @code{expr}. This is an extension to
+ANSI SQL.
+The @code{STDDEV()} form of this function is provided for Oracle compatability.
+
+@findex BIT_OR()
+@item BIT_OR(expr)
+Returns the bitwise @code{OR} of all bits in @code{expr}. The calculation is
+performed with 64-bit (@code{BIGINT} precision.
+
+@findex BIT_AND()
+@item BIT_AND(expr)
+Returns the bitwise @code{AND} of all bits in @code{expr}. The calculation is
+performed with 64-bit (@code{BIGINT} precision.
+@end table
+
+@strong{MySQL} has extended the use of @code{GROUP BY}. You can use columns or
+calculations in the @code{SELECT} expressions which don't appear in
+the @code{GROUP BY} part. This stands for @emph{any possible value for this
+group}. You can use this to get better performance by avoiding sorting and
+grouping on unnecessary items. For example, you don't need to group on
+@code{customer.name} in the following query:
+
+@example
+mysql> select order.custid,customer.name,max(payments)
+ from order,customer
+ where order.custid = customer.custid
+ GROUP BY order.custid;
+@end example
+
+In ANSI SQL, you would have to add @code{customer.name} to the @code{GROUP
+BY} clause. In @strong{MySQL}, the name is redundant if you don't run in
+ANSI mode.
+
+Don't use this feature if the columns you omit from the @code{GROUP BY} part
+aren't unique in the group!
+
+In some cases, you can use @code{MIN()} and @code{MAX()} to obtain a specific
+column value even if it isn't unique. The following gives the value of
+@code{column} from the row containing the smallest value in the @code{sort}
+column:
+
+@example
+substr(MIN(concat(sort,space(6-length(sort)),column),7,length(column)))
+@end example
+
+@cindex @code{ORDER BY}, aliases in
+@cindex Aliases, in @code{ORDER BY} clauses
+@cindex @code{GROUP BY}, aliases in
+@cindex Aliases, in @code{GROUP BY} clauses
+@cindex Expressions, aliases for
+@cindex Aliases, for expressions
+Note that if you are using @strong{MySQL} 3.22 (or earlier) or if you
+are trying to follow ANSI SQL, you can't use expressions in @code{GROUP
+BY} or @code{ORDER BY} clauses. You can work around this limitation by
+using an alias for the expression:
+
+@example
+mysql> SELECT id,FLOOR(value/100) AS val FROM tbl_name
+ GROUP BY id,val ORDER BY val;
+@end example
+
+In @code{MySQL} 3.23 you can do:
+
+@example
+mysql> SELECT id,FLOOR(value/100) FROM tbl_name ORDER BY RAND();
+@end example
+
+@findex CREATE DATABASE
+@node CREATE DATABASE, DROP DATABASE, Functions, Reference
+@section @code{CREATE DATABASE} syntax
+
+@example
+CREATE DATABASE [IF NOT EXISTS] db_name
+@end example
+
+@code{CREATE DATABASE} creates a database with the given name. Rules for
+allowable database names are given in @ref{Legal names}. An error occurs if
+the database already exists and you didn't specify @code{IF NOT EXISTS}.
+
+Databases in @strong{MySQL} are implemented as directories containing files
+that correspond to tables in the database. Because there are no tables in a
+database when it is initially created, the @code{CREATE DATABASE} statement
+only creates a directory under the @strong{MySQL} data directory.
+
+@cindex @code{mysqladmin}
+You can also create databases with @code{mysqladmin}.
+@xref{Programs}.
+
+@findex DROP DATABASE
+@node DROP DATABASE, CREATE TABLE, CREATE DATABASE, Reference
+@section @code{DROP DATABASE} syntax
+
+@example
+DROP DATABASE [IF EXISTS] db_name
+@end example
+
+@code{DROP DATABASE} drops all tables in the database and deletes the
+database. @strong{Be VERY careful with this command!}
+
+@code{DROP DATABASE} returns the number of files that were removed from the
+database directory. Normally, this is three times the number of tables,
+because each table corresponds to a @file{.MYD} file, a @file{.MYI} file and a
+@file{.frm} file.
+
+In @strong{MySQL} 3.22 or later, you can use the keywords @code{IF EXISTS} to
+prevent an error from occurring if the database doesn't exist.
+
+@cindex @code{mysqladmin}
+You can also drop databases with @code{mysqladmin}.
+@xref{Programs}.
+
+@findex CREATE TABLE
+@node CREATE TABLE, ALTER TABLE, DROP DATABASE, Reference
+@section @code{CREATE TABLE} syntax
+
+@menu
+* Silent column changes:: Silent column changes
+@end menu
+
+@example
+CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)]
+[table_options] [select_statement]
+
+create_definition:
+ col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
+ [PRIMARY KEY] [reference_definition]
+ or PRIMARY KEY (index_col_name,...)
+ or KEY [index_name] (index_col_name,...)
+ or INDEX [index_name] (index_col_name,...)
+ or UNIQUE [INDEX] [index_name] (index_col_name,...)
+ or [CONSTRAINT symbol] FOREIGN KEY index_name (index_col_name,...)
+ [reference_definition]
+ or CHECK (expr)
+
+type:
+ TINYINT[(length)] [UNSIGNED] [ZEROFILL]
+ or SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
+ or MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
+ or INT[(length)] [UNSIGNED] [ZEROFILL]
+ or INTEGER[(length)] [UNSIGNED] [ZEROFILL]
+ or BIGINT[(length)] [UNSIGNED] [ZEROFILL]
+ or REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
+ or DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
+ or FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
+ or DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL]
+ or NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL]
+ or CHAR(length) [BINARY]
+ or VARCHAR(length) [BINARY]
+ or DATE
+ or TIME
+ or TIMESTAMP
+ or DATETIME
+ or TINYBLOB
+ or BLOB
+ or MEDIUMBLOB
+ or LONGBLOB
+ or TINYTEXT
+ or TEXT
+ or MEDIUMTEXT
+ or LONGTEXT
+ or ENUM(value1,value2,value3,...)
+ or SET(value1,value2,value3,...)
+
+index_col_name:
+ col_name [(length)]
+
+reference_definition:
+ REFERENCES tbl_name [(index_col_name,...)]
+ [MATCH FULL | MATCH PARTIAL]
+ [ON DELETE reference_option]
+ [ON UPDATE reference_option]
+
+reference_option:
+ RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT
+
+table_options:
+ TYPE = @{ISAM | MYISAM | HEAP@}
+or AUTO_INCREMENT = #
+or AVG_ROW_LENGTH = #
+or CHECKSUM = @{0 | 1@}
+or COMMENT = "string"
+or MAX_ROWS = #
+or MIN_ROWS = #
+or PACK_KEYS = @{0 | 1@}
+or PASSWORD = "string"
+or DELAY_KEY_WRITE = @{0 | 1@}
+or ROW_FORMAT= @{ default | dynamic | static | compressed @}
+or RAID_TYPE= @{1 | STRIPED | RAID0 @} RAID_CHUNKS=# RAID_CHUNKSIZE=#;
+
+select_statement:
+ [IGNORE | REPLACE] SELECT ... (Some legal select statement)
+@end example
+
+@code{CREATE TABLE}
+creates a table with the given name in the current database. Rules for
+allowable table names are given in @ref{Legal names}. An error occurs if
+there is no current database or if the table already exists.
+
+In @strong{MySQL} 3.22 or later, the table name can be specified as
+@code{db_name.tbl_name}. This works whether or not there is a current
+database.
+
+In @strong{MySQL} 3.23, you can use the @code{TEMPORARY} keyword when you
+create a table. A temporary table will automatically be deleted if a
+connection dies and the name is per connection. This means that two different
+connections can both use the same temporary table name without conflicting
+with each other or with an existing table of the same name. (The existing table
+is hidden until the temporary table is deleted).
+
+In @strong{MySQL} 3.23 or later, you can use the keywords @code{IF NOT EXISTS}
+so that an error does not occur if the table already exists. Note that there
+is no verification that the table structures are identical.
+
+Each table @code{tbl_name} is represented by some files in the database
+directory. In the case of MyISAM-type tables you will get:
+
+@multitable @columnfractions .2 .8
+@item @strong{File} @tab @strong{Purpose}
+@item @code{tbl_name.frm} @tab Table definition (form) file
+@item @code{tbl_name.MYD} @tab Data file
+@item @code{tbl_name.MYI} @tab Index file
+@end multitable
+
+For more information on the properties of the various column types, see
+@ref{Column types}.
+
+@itemize @bullet
+@item
+If neither @code{NULL} nor @code{NOT NULL} is specified, the column
+is treated as though @code{NULL} had been specified.
+
+@item
+An integer column may have the additional attribute @code{AUTO_INCREMENT}.
+When you insert a value of @code{NULL} (recommended) or @code{0} into an
+@code{AUTO_INCREMENT} column, the column is set to @code{value+1}, where
+@code{value} is the largest value for the column currently in the table.
+@code{AUTO_INCREMENT} sequences begin with @code{1}.
+@xref{mysql_insert_id, , @code{mysql_insert_id()}}.
+
+If you delete the row containing the maximum value for an
+@code{AUTO_INCREMENT} column, the value will be reused with an ISAM
+table but not with a @code{MyISAM} table. If you delete all rows in the
+table with @code{DELETE FROM table_name} (without a @code{WHERE}) in
+@code{AUTOCOMMIT} mode, the sequence starts over for both table types.
+
+@strong{Note:} There can be only one @code{AUTO_INCREMENT} column per
+table, and it must be indexed. @strong{MySQL} 3.23 will also only work
+properly if the auto_increment column only has positive
+values. Inserting a negative number is regarded as inserting a very large
+positive number. This is done to avoid precision problems when
+numbers 'wrap' over from positive to negative and also to ensure that one
+doesn't accidently get a auto_increment column that contains 0.
+
+@cindex ODBC compatibility
+@cindex Compatibility, with ODBC
+To make @strong{MySQL} compatible with some ODBC applications, you can find
+the last inserted row with the following query:
+
+@example
+SELECT * FROM tbl_name WHERE auto_col IS NULL
+@end example
+
+@item
+@code{NULL} values are handled differently for @code{TIMESTAMP} columns than
+for other column types. You cannot store a literal @code{NULL} in a
+@code{TIMESTAMP} column; setting the column to @code{NULL} sets it to the
+current date and time. Because @code{TIMESTAMP} columns behave this way, the
+@code{NULL} and @code{NOT NULL} attributes do not apply in the normal way and
+are ignored if you specify them.
+
+On the other hand, to make it easier for @strong{MySQL} clients to use
+@code{TIMESTAMP} columns, the server reports that such columns may be
+assigned @code{NULL} values (which is true), even though @code{TIMESTAMP}
+never actually will contain a @code{NULL} value. You can see this when you
+use @code{DESCRIBE tbl_name} to get a description of your table.
+
+Note that setting a @code{TIMESTAMP} column to @code{0} is not the same
+as setting it to @code{NULL}, because @code{0} is a valid @code{TIMESTAMP}
+value.
+
+@item
+If no @code{DEFAULT} value is specified for a column, @strong{MySQL}
+automatically assigns one.
+
+If the column may take @code{NULL} as a value, the default value is
+@code{NULL}.
+
+If the column is declared as @code{NOT NULL}, the default value depends on
+the column type:
+
+@itemize @minus
+@item
+For numeric types other than those declared with the @code{AUTO_INCREMENT}
+attribute, the default is @code{0}. For an @code{AUTO_INCREMENT} column, the
+default value is the next value in the sequence.
+
+@item
+For date and time types other than @code{TIMESTAMP}, the default is the
+appropriate ``zero'' value for the type. For the first @code{TIMESTAMP}
+column in a table, the default value is the current date and time.
+@xref{Date and time types}.
+
+@item
+For string types other than @code{ENUM}, the default value is the empty string.
+For @code{ENUM}, the default is the first enumeration value.
+@end itemize
+
+@item
+@code{KEY} is a synonym for @code{INDEX}.
+
+@item
+In @strong{MySQL}, a @code{UNIQUE} key can have only distinct values. An
+error occurs if you try to add a new row with a key that matches an existing
+row.
+
+@item
+A @code{PRIMARY KEY} is a unique @code{KEY} with the extra constraint
+that all key columns must be defined as @code{NOT NULL}. In @strong{MySQL}
+the key is named @code{PRIMARY}. A table can have only one @code{PRIMARY KEY}.
+If you don't have a @code{PRIMARY KEY} and some applications ask for the
+@code{PRIMARY KEY} in your tables, @strong{MySQL} will return the first
+@code{UNIQUE} key, which doesn't have any @code{NULL} columns, as the
+@code{PRIMARY KEY}.
+
+@item
+A @code{PRIMARY KEY} can be a multiple-column index. However, you cannot
+create a multiple-column index using the @code{PRIMARY KEY} key attibute in a
+column specification. Doing so will mark only that single column as primary.
+You must use the @code{PRIMARY KEY(index_col_name, ...)} syntax.
+
+@item
+If the @code{PRIMARY} or @code{UNIQUE} key consists of only one column and this
+is of type integer, you can also refer to it as @code{_rowid}
+(new in 3.23.11).
+
+@item
+If you don't assign a name to an index, the index will be assigned the same
+name as the first @code{index_col_name}, with an optional suffix (@code{_2},
+@code{_3}, @code{...}) to make it unique. You can see index names for a
+table using @code{SHOW INDEX FROM tbl_name}.
+@xref{SHOW, , @code{SHOW}}.
+
+@item
+@cindex @code{NULL} values, and indexes
+@cindex Indexes, and @code{NULL} values
+Only the @code{MyISAM} table type supports indexes on columns that can have
+@code{NULL} values. In other cases you must declare such columns
+@code{NOT NULL} or an error results.
+
+@item
+With @code{col_name(length)} syntax, you can specify an index which
+uses only a part of a @code{CHAR} or @code{VARCHAR} column. This can
+make the index file much smaller.
+@xref{Indexes}.
+
+@item
+@cindex @code{BLOB} columns, indexing
+@cindex Indexes, and @code{BLOB} columns
+@cindex @code{TEXT} columns, indexing
+@cindex Indexes, and @code{TEXT} columns
+Only the @code{MyISAM} table type supports indexing on @code{BLOB} and
+@code{TEXT} columns. When putting an index on a @code{BLOB} or @code{TEXT}
+column you MUST always specify the length of the index:
+@example
+CREATE TABLE test (blob_col BLOB, index(blob_col(10)));
+@end example
+
+@item
+When you use @code{ORDER BY} or @code{GROUP BY} with a @code{TEXT} or
+@code{BLOB} column, only the first @code{max_sort_length} bytes are used.
+@xref{BLOB, , @code{BLOB}}.
+
+@item
+The @code{FOREIGN KEY}, @code{CHECK} and @code{REFERENCES} clauses don't
+actually do anything. The syntax for them is provided only for compatibility,
+to make it easier to port code from other SQL servers and to run applications
+that create tables with references.
+@xref{Missing functions}.
+
+@item
+Each @code{NULL} column takes one bit extra, rounded up to the nearest byte.
+
+@item
+The maximum record length in bytes can be calculated as follows:
+
+@example
+row length = 1
+ + (sum of column lengths)
+ + (number of NULL columns + 7)/8
+ + (number of variable-length columns)
+@end example
+
+@item The @code{table_options} and @code{SELECT} options is only
+implemented in @strong{MySQL} 3.23 and above.
+
+The different table types are:
+
+@multitable @columnfractions .20 .80
+@item ISAM @tab The original table handler. @xref{ISAM}.
+@item MyISAM @tab The new binary portable table handler. @xref{MyISAM}.
+@item HEAP @tab The data for this table is only stored in memory. @xref{HEAP}.
+@item BDB or Berkeley_db @tab Transaction safe tables @xref{BDB}.
+@end multitable
+@xref{Table types}.
+
+The other table options are used to optimize the behavior of the
+table. In most cases, you don't have to specify any of them.
+The options work for all table types, if not otherwise indicated.
+
+@multitable @columnfractions .20 .80
+@item @code{AUTO_INCREMENT} @tab The next auto_increment value you want to set for your table (MyISAM)
+@item @code{AVG_ROW_LENGTH} @tab An approximation of the average row length for your table. You only need to set this for tables with variable size records.
+@item @code{CHECKSUM} @tab Set this to 1 if you want @strong{MySQL} to maintain a checksum for all rows (makes the table a little slower to update but makes it easier to find corrupted tables) (MyISAM)
+@item @code{COMMENT} @tab A 60 character comment for your table
+@item @code{MAX_ROWS} @tab Max number of rows you plan to store in the table
+@item @code{MIN_ROWS} @tab Minimum number of rows you plan to store in the table
+@item @code{PACK_KEYS} @tab Set this to 1 if you want to have smaller index. This usually makes updates slower and reads faster (MyISAM, ISAM).
+@item @code{PASSWORD} @tab Encrypt the @code{.frm} file with a password. This option doesn't do anything in the standard @strong{MySQL} version.
+@item @code{DELAY_KEY_WRITE} @tab Set this to 1 if want to delay key table updates until the table is closed (MyISAM).
+@item @code{ROW_FORMAT} @tab Defines how the rows should be stored (for the future).
+@end multitable
+
+When you use a @code{MyISAM} table, @strong{MySQL} uses the product of
+@code{max_rows * avg_row_length} to decide how big the resulting table
+will be. If you don't specify any of the above options, the maximum size
+for a table will be 4G (or 2G if your operating systems only supports 2G
+tables).
+
+If you don't use @code{PACK_KEYS}, the default is to only pack strings,
+not numbers. If you use @code{PACK_KEYS=1}, numbers will be packed as well.
+
+When packing binary number keys, @strong{MySQL} will use prefix compression.
+This means that you will only get a big benefit of this if you have
+many numbers that are the same. Prefix compression means that every
+key needs one extra byte to indicate how many bytes of the previous key are
+the same for the next key (note that the pointer to the row is stored
+in high-byte-first-order directly after the key, to improve
+compression. This means that if you have many equal keys on two rows
+in a row, all following 'same' keys will usually only take 2 bytes
+(including the pointer to the row). Compare this to the ordinary case
+where the following keys will take 'storage_size_for_key' +
+pointer_size (usually 4). On the other hand, if all keys are
+totally different, you will lose 1 byte per key, if the key isn't a
+key that can have @code{NULL} values (In this case the packed key length will
+be stored in the same byte that is used to mark if a key is @code{NULL}).
+
+@item
+If you specify a @code{SELECT} after the @code{CREATE STATEMENT},
+@strong{MySQL} will create new fields for all elements in the
+@code{SELECT}. For example:
+
+@example
+mysql> CREATE TABLE test (a int not null auto_increment,
+ primary key (a), key(b))
+ TYPE=HEAP SELECT b,c from test2;
+@end example
+
+This will create a @code{HEAP} table with 3 columns. Note that the table will
+automatically be deleted if any errors occur while copying data
+into the table.
+@item
+The @code{RAID_TYPE} option will help you to break the 2G/4G limit on OSes
+that don't support big files. You can get also more speed from the I/O
+bottleneck by putting @code{RAID} directories on different physical disks.
+@code{RAID_TYPE} will work on any OS, as long as you have configured
+@strong{MySQL} with @code{--with-raid}. For now the only allowed
+@code{RAID_TYPE} is @code{STRIPED} (@code{1} and @code{RAID0} are aliases
+for this).
+
+If you specify @code{RAID_TYPE=STRIPED} for a @code{MyISAM} table,
+@code{MyISAM} will create @code{RAID_CHUNKS} sub-directories named 00,
+01, 02 in the database directory. In each of these directories
+@code{MyISAM} will create an @code{table_name.MYD}. When writing data
+to the data file, the @code{RAID} handler will map the first
+@code{RAID_CHUNKSIZE} *1024 bytes to the first file, the next
+@code{RAID_CHUNKSIZE} *1024 bytes to the next file and so on.
+@end itemize
+
+
+@node Silent column changes, , CREATE TABLE, CREATE TABLE
+@subsection Silent column specification changes
+
+In some cases, @strong{MySQL} silently changes a column specification from
+that given in a @code{CREATE TABLE} statement. (This may also occur with
+@code{ALTER TABLE}.)
+
+@itemize @bullet
+@item
+@code{VARCHAR} columns with a length less than four are changed to
+@code{CHAR}.
+
+@item
+If any column in a table has a variable length, the entire row is
+variable-length as a result. Therefore, if a table contains any
+variable-length columns (@code{VARCHAR}, @code{TEXT} or @code{BLOB}),
+all @code{CHAR} columns longer than three characters are changed to
+@code{VARCHAR} columns. This doesn't affect how you use the columns in
+any way; in @strong{MySQL}, @code{VARCHAR} is just a different way to
+store characters. @strong{MySQL} performs this conversion because it
+saves space and makes table operations faster. @xref{Table types}.
+
+@item
+@code{TIMESTAMP} display sizes must be even and in the range from 2 to 14.
+If you specify a display size of 0 or greater than 14, the size is coerced
+to 14. Odd-valued sizes in the range from 1 to 13 are coerced
+to the next higher even number.
+
+@item
+You cannot store a literal @code{NULL} in a @code{TIMESTAMP} column; setting
+it to @code{NULL} sets it to the current date and time. Because
+@code{TIMESTAMP} columns behave this way, the @code{NULL} and @code{NOT NULL}
+attributes do not apply in the normal way and are ignored if you specify
+them. @code{DESCRIBE tbl_name} always reports that a @code{TIMESTAMP}
+column may be assigned @code{NULL} values.
+
+@item
+@strong{MySQL} maps certain column types used by other SQL database vendors
+to @strong{MySQL} types. @xref{Other-vendor column types}.
+@end itemize
+
+If you want to see whether or not @strong{MySQL} used a column type other
+than the one you specified, issue a @code{DESCRIBE tbl_name} statement after
+creating or altering your table.
+
+@cindex @code{myisampack}
+Certain other column type changes may occur if you compress a table
+using @code{myisampack}. @xref{Compressed format}.
+
+@findex ALTER TABLE
+@node ALTER TABLE, DROP TABLE, CREATE TABLE, Reference
+@section @code{ALTER TABLE} syntax
+
+@example
+ALTER [IGNORE] TABLE tbl_name alter_spec [, alter_spec ...]
+
+alter_specification:
+ ADD [COLUMN] create_definition [FIRST | AFTER column_name ]
+ or ADD [COLUMN] (create_definition, create_definition,...)
+ or ADD INDEX [index_name] (index_col_name,...)
+ or ADD PRIMARY KEY (index_col_name,...)
+ or ADD UNIQUE [index_name] (index_col_name,...)
+ or ALTER [COLUMN] col_name @{SET DEFAULT literal | DROP DEFAULT@}
+ or CHANGE [COLUMN] old_col_name create_definition
+ or MODIFY [COLUMN] create_definition
+ or DROP [COLUMN] col_name
+ or DROP PRIMARY KEY
+ or DROP INDEX index_name
+ or RENAME [AS] new_tbl_name
+ or table_options
+@end example
+
+@code{ALTER TABLE} allows you to change the structure of an existing table.
+For example, you can add or delete columns, create or destroy indexes, change
+the type of existing columns, or rename columns or the table itself. You can
+also change the comment for the table and type of the table.
+@xref{CREATE TABLE, , @code{CREATE TABLE}}.
+
+If you use @code{ALTER TABLE} to change a column specification but
+@code{DESCRIBE tbl_name} indicates that your column was not changed, it is
+possible that @strong{MySQL} ignored your modification for one of the reasons
+described in @ref{Silent column changes}. For example, if you try to change
+a @code{VARCHAR} column to @code{CHAR}, @strong{MySQL} will still use
+@code{VARCHAR} if the table contains other variable-length columns.
+
+@code{ALTER TABLE} works by making a temporary copy of the original table.
+The alteration is performed on the copy, then the original table is
+deleted and the new one is renamed. This is done in such a way that
+all updates are automatically redirected to the new table without
+any failed updates. While @code{ALTER TABLE} is executing, the original
+table is readable by other clients. Updates and writes to the table
+are stalled until the new table is ready.
+
+@itemize @bullet
+@item
+To use @code{ALTER TABLE}, you need @strong{select}, @strong{insert},
+@strong{delete}, @strong{update}, @strong{create} and @strong{drop}
+privileges on the table.
+
+@item
+@code{IGNORE} is a @strong{MySQL} extension to ANSI SQL92.
+It controls how @code{ALTER TABLE} works if there are duplicates on
+unique keys in the new table.
+If @code{IGNORE} isn't specified, the copy is aborted and rolled back.
+If @code{IGNORE} is specified, then for rows with duplicates on a unique
+key, only the first row is used; the others are deleted.
+
+@item
+You can issue multiple @code{ADD}, @code{ALTER}, @code{DROP} and
+@code{CHANGE} clauses in a single @code{ALTER TABLE} statement. This is a
+@strong{MySQL} extension to ANSI SQL92, which allows only one of each clause
+per @code{ALTER TABLE} statement.
+
+@item
+@code{CHANGE col_name}, @code{DROP col_name} and @code{DROP
+INDEX} are @strong{MySQL} extensions to ANSI SQL92.
+
+@item
+@code{MODIFY} is an Oracle extension to @code{ALTER TABLE}.
+
+@item
+The optional word @code{COLUMN} is a pure noise word and can be omitted.
+
+@item
+If you use @code{ALTER TABLE tbl_name RENAME AS new_name} without any other
+options, @strong{MySQL} simply renames the files that correspond to the table
+@code{tbl_name}. There is no need to create the temporary table.
+
+@item
+@code{create_definition} clauses use the same syntax for @code{ADD} and
+@code{CHANGE} as for @code{CREATE TABLE}. Note that this syntax includes
+the column name, not just the column type.
+@xref{CREATE TABLE, , @code{CREATE TABLE}}.
+
+@item
+You can rename a column using a @code{CHANGE old_col_name create_definition}
+clause. To do so, specify the old and new column names and the type that
+the column currently has. For example, to rename an @code{INTEGER} column
+from @code{a} to @code{b}, you can do this:
+
+@example
+mysql> ALTER TABLE t1 CHANGE a b INTEGER;
+@end example
+
+If you want to change a column's type but not the name, @code{CHANGE}
+syntax still requires two column names even if they are the same. For
+example:
+
+@example
+mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;
+@end example
+
+However, as of @strong{MySQL} 3.22.16a, you can also use @code{MODIFY} to
+change a column's type without renaming it:
+
+@example
+mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
+@end example
+
+@item
+If you use @code{CHANGE} or @code{MODIFY} to shorten a column for which
+an index exists on part of the column (for instance, if you have an index
+on the first 10 characters of a @code{VARCHAR} column), you cannot make
+the column shorter than the number of characters that are indexed.
+
+@item
+When you change a column type using @code{CHANGE} or @code{MODIFY},
+@strong{MySQL} tries to convert data to the new type as well as possible.
+
+@item
+In @strong{MySQL} 3.22 or later, you can use @code{FIRST} or @code{ADD ...
+AFTER col_name} to add a column at a specific position within a table row.
+The default is to add the column last.
+
+@item
+@code{ALTER COLUMN} specifies a new default value for a column
+or removes the old default value.
+If the old default is removed and the column can be @code{NULL}, the new
+default is @code{NULL}. If the column cannot be @code{NULL}, @strong{MySQL}
+assigns a default value.
+Default value assignment is described in
+@ref{CREATE TABLE, , @code{CREATE TABLE}}.
+
+@item
+@code{DROP INDEX} removes an index. This is a @strong{MySQL} extension to
+ANSI SQL92.
+
+@item
+If columns are dropped from a table, the columns are also removed from any
+index of which they are a part. If all columns that make up an index are
+dropped, the index is dropped as well.
+
+@item
+@code{DROP PRIMARY KEY} drops the primary index. If no such
+index exists, it drops the first @code{UNIQUE} index in the table.
+(@strong{MySQL} marks the first @code{UNIQUE} key as the @code{PRIMARY KEY}
+if no @code{PRIMARY KEY} was specified explicitly.)
+
+@item
+@findex mysql_info()
+With the C API function @code{mysql_info()}, you can find out how many
+records were copied, and (when @code{IGNORE} is used) how many records were
+deleted due to duplication of unique key values.
+
+@item
+@cindex Foreign keys
+@cindex References
+The @code{FOREIGN KEY}, @code{CHECK} and @code{REFERENCES} clauses don't
+actually do anything. The syntax for them is provided only for compatibility,
+to make it easier to port code from other SQL servers and to run applications
+that create tables with references.
+@xref{Missing functions}.
+@end itemize
+
+Here is an example that shows some of the uses of @code{ALTER TABLE}. We
+begin with a table @code{t1} that is created as shown below:
+
+@example
+mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));
+@end example
+
+To rename the table from @code{t1} to @code{t2}:
+
+@example
+mysql> ALTER TABLE t1 RENAME t2;
+@end example
+
+To change column @code{a} from @code{INTEGER} to @code{TINYINT NOT NULL}
+(leaving the name the same), and to change column @code{b} from
+@code{CHAR(10)} to @code{CHAR(20)} as well as renaming it from @code{b} to
+@code{c}:
+
+@example
+mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);
+@end example
+
+To add a new @code{TIMESTAMP} column named @code{d}:
+
+@example
+mysql> ALTER TABLE t2 ADD d TIMESTAMP;
+@end example
+
+To add an index on column @code{d}, and make column @code{a} the primary key:
+
+@example
+mysql> ALTER TABLE t2 ADD INDEX (d), ADD PRIMARY KEY (a);
+@end example
+
+To remove column @code{c}:
+
+@example
+mysql> ALTER TABLE t2 DROP COLUMN c;
+@end example
+
+To add a new @code{AUTO_INCREMENT} integer column named @code{c}:
+
+@example
+mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ ADD INDEX (c);
+@end example
+
+Note that we indexed @code{c}, because @code{AUTO_INCREMENT} columns must be
+indexed, and also that we declare @code{c} as @code{NOT NULL}, because
+indexed columns cannot be @code{NULL}.
+
+When you add an @code{AUTO_INCREMENT} column, column values are filled in
+with sequence numbers for you automatically.
+
+See also @xref{ALTER TABLE problems, , @code{ALTER TABLE} problems}.
+
+@findex DROP TABLE
+@node DROP TABLE, OPTIMIZE TABLE, ALTER TABLE, Reference
+@section @code{DROP TABLE} syntax
+
+@example
+DROP TABLE [IF EXISTS] tbl_name [, tbl_name,...]
+@end example
+
+@code{DROP TABLE} removes one or more tables. All table data and the table
+definition are @emph{removed}, so @strong{be careful} with this command!
+
+In @strong{MySQL} 3.22 or later, you can use the keywords @code{IF EXISTS} to
+prevent an error from occurring for tables that don't exist.
+
+@findex OPTIMIZE TABLE
+@node OPTIMIZE TABLE, CHECK TABLE, DROP TABLE, Reference
+@section @code{OPTIMIZE TABLE} syntax
+
+@example
+OPTIMIZE TABLE tbl_name
+@end example
+
+@code{OPTIMIZE TABLE} should be used if you have deleted a large part of a
+table or if you have made many changes to a table with variable-length rows
+(tables that have @code{VARCHAR}, @code{BLOB} or @code{TEXT} columns).
+Deleted records are maintained in a linked list and subsequent @code{INSERT}
+operations reuse old record positions. You can use @code{OPTIMIZE TABLE} to
+reclaim the unused space.
+
+@code{OPTIMIZE TABLE} works by making a temporary copy of the original
+table; The old table is copied to the new table (without the unused
+rows), then the original table is deleted and the new one is
+renamed. While @code{OPTIMIZE TABLE} is executing, the original table is
+readable by other clients. Updates and writes to the table are stalled
+until the new table is ready. This is done in such a way that all updates
+are automatically redirected to the new table without any failed updates.
+
+@findex CHECK TABLE
+@node CHECK TABLE, ANALYZE TABLE, OPTIMIZE TABLE, Reference
+@section @code{CHECK TABLE} syntax
+
+@example
+CHECK TABLE tbl_name[,tbl_name...] [TYPE = QUICK]
+@end example
+
+Check the table(s) for errors. The command returns a table with the following
+columns:
+
+@multitable @columnfractions .35 .65
+@item Table @tab Table name
+@item Op @tab Always 'check'
+@item Msg_type @tab One of @code{status}, @code{error}, @code{info} or @code{warning}.
+@item Msg_text @tab The message.
+@end multitable
+
+Note that you can get many rows of information for each checked table. The
+last one row will be of @code{Msg_type status} and should normally be
+@code{OK}. If you don't get @code{OK}, you should normally run a repair of
+the table. @xref{Table maintenance}.
+
+If @code{TYPE=QUICK} is given then @strong{MySQL} will not scan the rows
+for table with fixed size records.
+
+@code{CHECK TABLE} only works on @code{MyISAM} tables and is the same things
+as running @code{myisamchk -m table_name} on the table.
+
+@findex ANALYZE TABLE
+@node ANALYZE TABLE, REPAIR TABLE, CHECK TABLE, Reference
+@section @code{ANALYZE TABLE} syntax
+
+@example
+ANALYZE TABLE tbl_name[,tbl_name...]
+@end example
+
+Analyze and store the key distribution for the table. During the
+analyze the table is locked with a read lock.
+This is equivalent of running @code{myisamchk -a} on the table.
+
+@strong{MySQL} uses the stored key distribution to decide in which order
+tables should be joined when one does a join on something else than a
+constant.
+
+The command returns a table with the following columns:
+
+@multitable @columnfractions .35 .65
+@item Table @tab Table name
+@item Op @tab Always 'analyze
+@item Msg_type @tab One of @code{status}, @code{error}, @code{info} or @code{warning}.
+@item Msg_text @tab The message.
+@end multitable
+
+You can check the stored key distribution with the @code{SHOW INDEX} command.
+@xref{SHOW DATABASE INFO}.
+
+@findex REPAIR TABLE
+@node REPAIR TABLE, DELETE, ANALYZE TABLE, Reference
+@section @code{REPAIR TABLE} syntax
+
+@example
+REPAIR TABLE tbl_name[,tbl_name...] [TYPE = QUICK]
+@end example
+
+@code{REPAIR TABLE} only works on @code{MyISAM} tables and is the same things
+as running @code{myisamchk -r table_name} on the table.
+
+Repair the corrupted table. The command returns a table with the following
+columns:
+
+@multitable @columnfractions .35 .65
+@item Table @tab Table name
+@item Op @tab Always 'repair'
+@item Msg_type @tab One of @code{status}, @code{error}, @code{info} or @code{warning}.
+@item Msg_text @tab The message.
+@end multitable
+
+Note that you can get many rows of information for each repaired
+table. The last one row will be of @code{Msg_type status} and should
+normally be @code{OK}. If you don't get @code{OK}, you should try
+repairing the table with @code{myisamchk -o}, as @code{REPAIR TABLE}
+does not yet implement all the options of @code{myisamchk}. In the near
+future, we will make it more flexible.
+
+If @code{TYPE=QUICK} is given then @strong{MySQL} will try to do a
+@code{REPAIR} of only the index tree.
+
+@findex DELETE
+@node DELETE, SELECT, REPAIR TABLE, Reference
+@section @code{DELETE} syntax
+
+@example
+DELETE [LOW_PRIORITY] FROM tbl_name
+ [WHERE where_definition] [LIMIT rows]
+@end example
+
+@code{DELETE} deletes rows from @code{tbl_name} that satisfy the condition
+given by @code{where_definition}, and returns the number of records deleted.
+
+If you issue a @code{DELETE} with no @code{WHERE} clause, all rows are
+deleted. If you do this in @code{AUTOCOMMIT} mode, @strong{MySQL} does
+this by recreating the table as an empty table, which is much faster
+than deleting each row. In this case, @code{DELETE} returns zero as the
+number of affected records. (@strong{MySQL} can't return the number of
+rows that were actually deleted, because the recreate is done without
+opening the data files. As long as the table definition file
+@file{tbl_name.frm} is valid, the table can be recreated this way, even
+if the data or index files have become corrupted.).
+
+If you really want to know how many records are deleted when you are deleting
+all rows, and are willing to suffer a speed penalty, you can use a
+@code{DELETE} statement of this form:
+
+@example
+mysql> DELETE FROM tbl_name WHERE 1>0;
+@end example
+
+Note that this is MUCH slower than @code{DELETE FROM tbl_name} with no
+@code{WHERE} clause, because it deletes rows one at a time.
+
+If you specify the keyword @code{LOW_PRIORITY}, execution of the
+@code{DELETE} is delayed until no other clients are reading from the table.
+
+Deleted records are maintained in a linked list and subsequent @code{INSERT}
+operations reuse old record positions. To reclaim unused space and reduce
+file sizes, use the @code{OPTIMIZE TABLE} statement or the @code{myisamchk}
+utility to reorganize tables. @code{OPTIMIZE TABLE} is easier, but
+@code{myisamchk} is faster.
+@xref{OPTIMIZE TABLE, , @code{OPTIMIZE TABLE}}, and
+@ref{Optimization}.
+
+The @strong{MySQL}-specific @code{LIMIT rows} option to @code{DELETE} tells
+the server the maximum number of rows to be deleted before control is
+returned to the client. This can be used to ensure that a specific
+@code{DELETE} command doesn't take too much time. You can simply repeat
+the @code{DELETE} command until the number of affected rows is less than
+the @code{LIMIT} value.
+
+@findex SELECT
+@node SELECT, JOIN, DELETE, Reference
+@section @code{SELECT} syntax
+
+@example
+SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
+ [HIGH_PRIORITY]
+ [DISTINCT | DISTINCTROW | ALL]
+ select_expression,...
+ [INTO @{OUTFILE | DUMPFILE@} 'file_name' export_options]
+ [FROM table_references
+ [WHERE where_definition]
+ [GROUP BY @{unsigned_integer | col_name | formula@}]
+ [HAVING where_definition]
+ [ORDER BY @{unsigned_integer | col_name | formula@} [ASC | DESC] ,...]
+ [LIMIT [offset,] rows]
+ [PROCEDURE procedure_name] ]
+@end example
+
+@code{SELECT} is used to retrieve rows selected from one or more tables.
+@code{select_expression} indicates the columns you want to retrieve.
+@code{SELECT} may also be used to retrieve rows computed without reference to
+any table. For example:
+
+@example
+mysql> SELECT 1 + 1;
+ -> 2
+@end example
+
+All keywords used must be given in exactly the order shown above. For example,
+a @code{HAVING} clause must come after any @code{GROUP BY} clause and before
+any @code{ORDER BY} clause.
+
+@itemize @bullet
+
+@item
+@cindex Aliases, on expressions
+@cindex Expression aliases
+A @code{SELECT} expression may be given an alias using @code{AS}. The alias
+is used as the expression's column name and can be used with
+@code{ORDER BY} or @code{HAVING} clauses. For example:
+
+@example
+mysql> select concat(last_name,', ',first_name) AS full_name
+ from mytable ORDER BY full_name;
+@end example
+
+@item
+The @code{FROM table_references} clause indicates the tables from which to
+retrieve rows. If you name more than one table, you are performing a
+join. For information on join syntax, see @ref{JOIN, , @code{JOIN}}.
+
+@item
+You can refer to a column as @code{col_name}, @code{tbl_name.col_name} or
+@code{db_name.tbl_name.col_name}. You need not specify a @code{tbl_name} or
+@code{db_name.tbl_name} prefix for a column reference in a @code{SELECT}
+statement unless the reference would be ambiguous. See @ref{Legal names},
+for examples of ambiguity that require the more explicit column reference
+forms.
+
+@item
+@cindex Aliases, for tables
+@cindex Table aliases
+A table reference may be aliased using @code{tbl_name [AS] alias_name}.
+
+@example
+mysql> select t1.name, t2.salary from employee AS t1, info AS t2
+ where t1.name = t2.name;
+mysql> select t1.name, t2.salary from employee t1, info t2
+ where t1.name = t2.name;
+@end example
+
+@item
+Columns selected for output may be referred to in @code{ORDER BY} and
+@code{GROUP BY} clauses using column names, column aliases or column
+positions. Column positions begin with 1.
+
+@example
+mysql> select college, region, seed from tournament
+ ORDER BY region, seed;
+mysql> select college, region AS r, seed AS s from tournament
+ ORDER BY r, s;
+mysql> select college, region, seed from tournament
+ ORDER BY 2, 3;
+@end example
+
+To sort in reverse order, add the @code{DESC} (descending) keyword to the
+name of the column in the @code{ORDER BY} clause that you are sorting by.
+The default is ascending order; this may be specified explicitly using
+the @code{ASC} keyword.
+
+@item
+The @code{HAVING} clause can refer to any column or alias named in the
+@code{select_expression}. It is applied last, just before items are sent to
+the client, with no optimization. Don't use @code{HAVING} for items that
+should be in the @code{WHERE} clause. For example, do not write this:
+
+@example
+mysql> select col_name from tbl_name HAVING col_name > 0;
+@end example
+
+Write this instead:
+
+@example
+mysql> select col_name from tbl_name WHERE col_name > 0;
+@end example
+
+In @strong{MySQL} 3.22.5 or later, you can also write queries like this:
+
+@example
+mysql> select user,max(salary) from users
+ group by user HAVING max(salary)>10;
+@end example
+
+In older @strong{MySQL} versions, you can write this instead:
+
+@example
+mysql> select user,max(salary) AS sum from users
+ group by user HAVING sum>10;
+@end example
+
+@item
+@code{SQL_SMALL_RESULT}, @code{SQL_BIG_RESULT}, @code{SQL_BUFFER_RESULT},
+@code{STRAIGHT_JOIN} and @code{HIGH_PRIORITY} are @strong{MySQL} extensions
+to ANSI SQL92.
+
+@item
+@code{HIGH_PRIORITY} will give the @code{SELECT} higher priority than
+a statement that updates a table. You should only use this for queries
+that are very fast and must be done at once. A @code{SELECT HIGH_PRIORITY}
+query will run if the table is locked for read even if there is an update
+statement that is waiting for the table to be free.
+
+@item
+@code{SQL_BIG_RESULT} can be used with @code{GROUP BY} or @code{DISTINCT}
+to tell the optimizer that the result set will have many rows. In this case,
+@strong{MySQL} will directly use disk based temporary tables if needed.
+@strong{MySQL} will also in this case prefer sorting to doing a
+temporary table with a key on the @code{GROUP BY} elements.
+
+@item
+@code{SQL_BUFFER_RESULT} will put force the result to be put into a temporary
+table. This will help @strong{MySQL} free the table locks early and will help
+in cases where it takes a long time to send the result set to the client.
+
+@item
+@code{SQL_SMALL_RESULT}, a @strong{MySQL}-specific option, can be used
+with @code{GROUP BY} or @code{DISTINCT} to tell the optimizer that the
+result set will be small. In this case, @strong{MySQL} will use fast
+temporary tables to store the resulting table instead of using sorting. In
+@strong{MySQL} 3.23 this shouldn't normally be needed.
+
+@item
+@code{STRAIGHT_JOIN} forces the optimizer to join the tables in the order in
+which they are listed in the @code{FROM} clause. You can use this to speed up
+a query if the optimizer joins the tables in non-optimal order.
+@xref{EXPLAIN, , @code{EXPLAIN}}.
+
+@item
+The @code{LIMIT} clause can be used to constrain the number of rows returned
+by the @code{SELECT} statement. @code{LIMIT} takes one or two numeric
+arguments.
+
+If two arguments are given, the first specifies the offset of the first row to
+return, the second specifies the maximum number of rows to return.
+The offset of the initial row is 0 (not 1).
+
+@example
+mysql> select * from table LIMIT 5,10; # Retrieve rows 6-15
+@end example
+
+If one argument is given, it indicates the maximum number of rows to return.
+
+@example
+mysql> select * from table LIMIT 5; # Retrieve first 5 rows
+@end example
+
+In other words, @code{LIMIT n} is equivalent to @code{LIMIT 0,n}.
+
+@item
+@tindex /etc/passwd
+The @code{SELECT ... INTO OUTFILE 'file_name'} form of @code{SELECT} writes
+the selected rows to a file. The file is created on the server host, and
+cannot already exist (among other things, this prevents database tables and
+files such as @file{/etc/passwd} from being destroyed). You must have the
+@strong{file} privilege on the server host to use this form of @code{SELECT}.
+
+@code{SELECT ... INTO OUTFILE} is the complement of @code{LOAD DATA
+INFILE}; the syntax for the @code{export_options} part of the statement
+consists of the same @code{FIELDS} and @code{LINES} clauses that are used
+with the @code{LOAD DATA INFILE} statement.
+@xref{LOAD DATA, , @code{LOAD DATA}}.
+
+In the resulting text file, only the following characters are escaped by
+the @code{ESCAPED BY} character:
+
+@itemize @bullet
+@item The @code{ESCAPED BY} character
+@item The first character in @code{FIELDS TERMINATED BY}
+@item The first character in @code{LINES TERMINATED BY}
+@end itemize
+
+Additionally, @code{ASCII 0} is converted to @code{ESCAPED BY} followed by 0
+(@code{ASCII 48}).
+
+The reason for the above is that you MUST escape any @code{FIELDS
+TERMINATED BY}, @code{ESCAPED BY} or @code{LINES TERMINATED BY}
+characters to reliably be able to read the file
+back. @code{ASCII 0} is escaped to make it easier to view with some
+pagers.
+
+As the resulting file doesn't have to conform to the SQL syntax, nothing
+else need be escaped.
+@end itemize
+
+@findex DUMPFILE
+If you use @code{INTO DUMPFILE} instead of @code{INTO OUTFILE} @strong{MySQL}
+will only write one row into the file, without any column or line
+terminations and without any escaping. This is useful if you want to
+store a blob in a file.
+
+@findex JOIN
+@findex INNER JOIN
+@findex CROSS JOIN
+@findex LEFT JOIN
+@findex LEFT OUTER JOIN
+@findex NATURAL LEFT JOIN
+@findex NATURAL LEFT OUTER JOIN
+@findex STRAIGHT_JOIN
+@node JOIN, INSERT, SELECT, Reference
+@section @code{JOIN} syntax
+
+@strong{MySQL} supports the following @code{JOIN} syntaxes for use in
+@code{SELECT} statements:
+
+@example
+table_reference, table_reference
+table_reference [CROSS] JOIN table_reference
+table_reference INNER JOIN table_reference join_condition
+table_reference STRAIGHT_JOIN table_reference
+table_reference LEFT [OUTER] JOIN table_reference join_condition
+table_reference LEFT [OUTER] JOIN table_reference
+table_reference NATURAL [LEFT [OUTER]] JOIN table_reference
+@{ oj table_reference LEFT OUTER JOIN table_reference ON conditional_expr @}
+@end example
+
+Where @code{table_reference} is defined as
+@example
+table_name [[AS] alias] [USE INDEX (key_list)] [IGNORE INDEX (key_list)]
+@end example
+
+and @code{join_condition} is defined as
+
+@example
+ON conditional_expr |
+USING (column_list)
+@end example
+
+Note that in version before 3.23.16 the @code{INNER JOIN} didn't take
+a join condition!
+
+@cindex ODBC compatibility
+@cindex Compatibility, with ODBC
+The last @code{LEFT OUTER JOIN} syntax shown above exists only for
+compatibility with ODBC.
+
+@itemize @bullet
+@item
+A table reference may be aliased using @code{tbl_name AS alias_name} or
+@code{tbl_name alias_name}.
+
+@example
+mysql> select t1.name, t2.salary from employee AS t1, info AS t2
+ where t1.name = t2.name;
+@end example
+
+@item
+@code{INNER JOIN} and @code{,} (comma) are semantically equivalent.
+Both do a full join between the tables used. Normally, you specify how
+the tables should be linked in the @code{WHERE} condition.
+
+@item
+The @code{ON} conditional is any conditional of the form that may be used in
+a @code{WHERE} clause.
+
+@item
+If there is no matching record for the right table in the @code{ON} or
+@code{USING} part in a @code{LEFT JOIN}, a row with all columns set to
+@code{NULL} is used for the right table. You can use this fact to find
+records in a table that have no counterpart in another table:
+
+@example
+mysql> select table1.* from table1
+ LEFT JOIN table2 ON table1.id=table2.id
+ where table2.id is NULL;
+@end example
+
+This example finds all rows in @code{table1} with an @code{id} value that is
+not present in @code{table2} (i.e., all rows in @code{table1} with no
+corresponding row in @code{table2}). This assumes that @code{table2.id} is
+declared @code{NOT NULL}, of course.
+
+@item
+The @code{USING} @code{(column_list)} clause names a list of columns that must
+exist in both tables. A @code{USING} clause such as:
+
+@example
+A LEFT JOIN B USING (C1,C2,C3,...)
+@end example
+
+is defined to be semantically identical to an @code{ON} expression like
+this:
+
+@example
+A.C1=B.C1 AND A.C2=B.C2 AND A.C3=B.C3,...
+@end example
+
+@item
+The @code{NATURAL [LEFT] JOIN} of two tables is defined to be
+semantically equivalent to a @code{INNER JOIN} or a @code{LEFT JOIN}
+with a @code{USING} clause that names all columns that exist in both
+tables.
+
+@item
+@code{STRAIGHT_JOIN} is identical to @code{JOIN}, except that the left table
+is always read before the right table. This can be used for those (few)
+cases where the join optimizer puts the tables in the wrong order.
+
+@item
+As of @strong{MySQL} 3.23.12, you can give hints about which
+index @strong{MySQL} should use when retrieving information from a
+table. This is useful if @code{EXPLAIN} shows that @strong{MySQL} is
+using the wrong index. By specifying @code{USE INDEX (key_list)}, you
+can tell @strong{MySQL} to use only one of the specified indexes to
+find rows in the table. The alternative syntax @code{IGNORE INDEX
+(key_list)} can be used to tell @strong{MySQL} to not use some
+particular index.
+@end itemize
+
+Some examples:
+
+@example
+mysql> select * from table1,table2 where table1.id=table2.id;
+mysql> select * from table1 LEFT JOIN table2 ON table1.id=table2.id;
+mysql> select * from table1 LEFT JOIN table2 USING (id);
+mysql> select * from table1 LEFT JOIN table2 ON table1.id=table2.id
+ LEFT JOIN table3 ON table2.id=table3.id;
+mysql> select * from table1 USE INDEX (key1,key2) WHERE key1=1 and key2=2 AND
+ key3=3;
+mysql> select * from table1 IGNORE INDEX (key3) WHERE key1=1 and key2=2 AND
+ key3=3;
+@end example
+
+@xref{LEFT JOIN optimization, , @code{LEFT JOIN} optimization}.
+
+@findex INSERT
+@node INSERT, REPLACE, JOIN, Reference
+@section @code{INSERT} syntax
+
+@example
+ INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
+ [INTO] tbl_name [(col_name,...)]
+ VALUES (expression,...),(...),...
+or INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
+ [INTO] tbl_name [(col_name,...)]
+ SELECT ...
+or INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
+ [INTO] tbl_name
+ SET col_name=expression, col_name=expression, ...
+@end example
+
+@code{INSERT} inserts new rows into an existing table. The @code{INSERT ...
+VALUES} form of the statement inserts rows based on explicitly-specified
+values. The @code{INSERT ... SELECT} form inserts rows selected from another
+table or tables. The @code{INSERT ... VALUES} form with multiple value lists
+is supported in @strong{MySQL} 3.22.5 or later. The
+@code{col_name=expression} syntax is supported in @strong{MySQL} 3.22.10 or
+later.
+
+@code{tbl_name} is the table into which rows should be inserted. The column
+name list or the @code{SET} clause indicates which columns the statement
+specifies values for.
+
+@itemize @bullet
+@item
+If you specify no column list for @code{INSERT ... VALUES} or @code{INSERT
+... SELECT}, values for all columns must be provided in the
+@code{VALUES()} list or by the @code{SELECT}. If you don't know the order of
+the columns in the table, use @code{DESCRIBE tbl_name} to find out.
+
+@item
+Any column not explicitly given a value is set to its default value. For
+example, if you specify a column list that doesn't name all the columns in
+the table, unnamed columns are set to their default values. Default value
+assignment is described in @ref{CREATE TABLE, , @code{CREATE TABLE}}.
+
+@item
+An @code{expression} may refer to any column that was set earlier in a value
+list. For example, you can say this:
+
+@example
+mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);
+@end example
+
+But not this:
+
+@example
+mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);
+@end example
+
+@item
+If you specify the keyword @code{LOW_PRIORITY}, execution of the
+@code{INSERT} is delayed until no other clients are reading from the table.
+In this case the client has to wait until the insert statement is completed,
+which may take a long time if the table is in heavy use. This is in
+contrast to @code{INSERT DELAYED} which lets the client continue at once.
+
+@item
+If you specify the keyword @code{IGNORE} in an @code{INSERT} with many value
+rows, any rows which duplicate an existing @code{PRIMARY} or @code{UNIQUE}
+key in the table are ignored and are not inserted. If you do not specify
+@code{IGNORE}, the insert is aborted if there is any row that duplicates an
+existing key value. You can check with the C API function
+@code{mysql_info()} how many rows were inserted into the table.
+
+@item
+If @strong{MySQL} was configured using the @code{DONT_USE_DEFAULT_FIELDS}
+option, @code{INSERT} statements generate an error unless you explicitly
+specify values for all columns that require a non-@code{NULL} value.
+@xref{configure options, , @code{configure} options}.
+
+@item
+The following conditions hold for a @code{INSERT INTO ... SELECT} statement:
+
+@itemize @minus
+@item
+The query cannot contain an @code{ORDER BY} clause.
+
+@item
+The target table of the @code{INSERT} statement cannot appear in the
+@code{FROM} clause of the @code{SELECT} part of the query, because it's
+forbidden in ANSI SQL to @code{SELECT} from the same table into which you are
+@code{INSERT}ing. (The problem is that the @code{SELECT} possibly would
+find records that were inserted earlier during the same run. When using
+sub-select clauses, the situation could easily be very confusing!)
+
+@item
+@code{AUTO_INCREMENT} columns work as usual.
+@end itemize
+@end itemize
+
+@findex mysql_info()
+If you use @code{INSERT ... SELECT} or a @code{INSERT ... VALUES}
+statement with multiple value lists, you can use the C API function
+@code{mysql_info()} to get information about the query. The format of the
+information string is shown below:
+
+@example
+Records: 100 Duplicates: 0 Warnings: 0
+@end example
+
+@code{Duplicates} indicates the number of rows that couldn't be inserted
+because they would duplicate some existing unique index value.
+@code{Warnings} indicates the number of attempts to insert column values that
+were problematic in some way. Warnings can occur under any of the following
+conditions:
+
+@itemize @bullet
+@item
+Inserting @code{NULL} into a column that has been declared @code{NOT NULL}.
+The column is set to its default value.
+
+@item
+Setting a numeric column to a value that lies outside the column's range.
+The value is clipped to the appropriate endpoint of the range.
+
+@item
+Setting a numeric column to a value such as @code{'10.34 a'}. The trailing
+garbage is stripped and the remaining numeric part is inserted. If the value
+doesn't make sense as a number at all, the column is set to @code{0}.
+
+@item
+Inserting a string into a @code{CHAR}, @code{VARCHAR}, @code{TEXT} or
+@code{BLOB} column that exceeds the column's maximum length. The value is
+truncated to the column's maximum length.
+
+@item
+Inserting a value into a date or time column that is illegal for the column
+type. The column is set to the appropriate ``zero'' value for the type.
+@end itemize
+
+@findex INSERT DELAYED
+@findex DELAYED
+
+The @code{DELAYED} option
+for the
+@code{INSERT} statement is a @strong{MySQL}-specific option that is very
+useful if you have clients that can't wait for the @code{INSERT} to complete.
+This is a common problem when you use @strong{MySQL} for logging and you also
+periodically run @code{SELECT} statements that take a long time to complete.
+@code{DELAYED} was introduced in @strong{MySQL} 3.22.15. It is a
+@strong{MySQL} extension to ANSI SQL92.
+
+When you use @code{INSERT DELAYED}, the client will get an ok at once
+and the row will be inserted when the table is not in use by any other thread.
+
+Another major benefit of using @code{INSERT DELAYED} is that inserts
+from many clients are bundled together and written in one block. This is much
+faster than doing many separate inserts.
+
+Note that currently the queued rows are only stored in memory until they are
+inserted into the table. This means that if you kill @code{mysqld}
+the hard way (@code{kill -9}) or if @code{mysqld} dies unexpectedly, any
+queued rows that weren't written to disk are lost!
+
+The following describes in detail what happens when you use the
+@code{DELAYED} option to @code{INSERT} or @code{REPLACE}. In this
+description, the ``thread'' is the thread that received an @code{INSERT
+DELAYED} command and ``handler'' is the thread that handles all
+@code{INSERT DELAYED} statements for a particular table.
+
+@itemize @bullet
+@item
+When a thread executes a @code{DELAYED} statement for a table, a handler
+thread is created to process all @code{DELAYED} statements for the table, if
+no such handler already exists.
+
+@item
+The thread checks whether or not the handler has acquired a @code{DELAYED}
+lock already; if not, it tells the handler thread to do so. The
+@code{DELAYED} lock can be obtained even if other threads have a @code{READ}
+or @code{WRITE} lock on the table. However, the handler will wait for all
+@code{ALTER TABLE} locks or @code{FLUSH TABLES} to ensure that the table
+structure is up to date.
+
+@item
+The thread executes the @code{INSERT} statement but instead of writing
+the row to the table it puts a copy of the final row into a queue that
+is managed by the handler thread. Any syntax errors are noticed by the
+thread and reported to the client program.
+
+@item
+The client can't report the number of duplicates or the @code{AUTO_INCREMENT}
+value for the resulting row; it can't obtain them from the server, because
+the @code{INSERT} returns before the insert operation has been completed. If
+you use the C API, the @code{mysql_info()} function doesn't return anything
+meaningful, for the same reason.
+
+@item
+The update log is updated by the handler thread when the row is inserted into
+the table. In case of multiple-row inserts, the update log is updated when
+the first row is inserted.
+
+@item
+After every @code{delayed_insert_limit} rows are written, the handler checks
+whether or not any @code{SELECT} statements are still pending. If so, it
+allows these to execute before continuing.
+
+@item
+When the handler has no more rows in its queue, the table is unlocked. If no
+new @code{INSERT DELAYED} commands are received within
+@code{delayed_insert_timeout} seconds, the handler terminates.
+
+@item
+If more than @code{delayed_queue_size} rows are pending already in a specific
+handler queue, the thread waits until there is room in the queue. This is
+useful to ensure that the @code{mysqld} server doesn't use all memory for the
+delayed memory queue.
+
+@item
+The handler thread will show up in the @strong{MySQL} process list
+with @code{delayed_insert} in the @code{Command} column. It will
+be killed if you execute a @code{FLUSH TABLES} command or kill it with
+@code{KILL thread_id}. However, it will first store all queued rows into the
+table before exiting. During this time it will not accept any new
+@code{INSERT} commands from another thread. If you execute an @code{INSERT
+DELAYED} command after this, a new handler thread will be created.
+
+@item
+Note that the above means that @code{INSERT DELAYED} commands have higher
+priority than normal @code{INSERT} commands if there is an @code{INSERT
+DELAYED} handler already running! Other update commands will have to wait
+until the @code{INSERT DELAYED} queue is empty, someone kills the handler
+thread (with @code{KILL thread_id}) or someone executes @code{FLUSH TABLES}.
+
+@item
+The following status variables provide information about @code{INSERT
+DELAYED} commands:
+
+@multitable @columnfractions .35 .65
+@item @code{Delayed_insert_threads} @tab Number of handler threads
+@item @code{Delayed_writes} @tab Number of rows written with @code{INSERT DELAYED}
+@item @code{Not_flushed_delayed_rows} @tab Number of rows waiting to be written
+@end multitable
+
+You can view these variables by issuing a @code{SHOW STATUS} statement or
+by executing a @code{mysqladmin extended-status} command.
+@end itemize
+
+Note that @code{INSERT DELAYED} is slower than a normal INSERT if the
+table is not in use. There is also the additional overhead for the
+server to handle a separate thread for each table on which you use
+@code{INSERT DELAYED}. This means that you should only use @code{INSERT
+DELAYED} when you are really sure you need it!
+
+@findex REPLACE
+@node REPLACE, LOAD DATA, INSERT, Reference
+@section @code{REPLACE} syntax
+
+@example
+ REPLACE [LOW_PRIORITY | DELAYED]
+ [INTO] tbl_name [(col_name,...)]
+ VALUES (expression,...)
+or REPLACE [LOW_PRIORITY | DELAYED]
+ [INTO] tbl_name [(col_name,...)]
+ SELECT ...
+or REPLACE [LOW_PRIORITY | DELAYED]
+ [INTO] tbl_name
+ SET col_name=expression, col_name=expression,...
+@end example
+
+@code{REPLACE} works exactly like @code{INSERT}, except that if an old
+record in the table has the same value as a new record on a unique index,
+the old record is deleted before the new record is inserted.
+@xref{INSERT, , @code{INSERT}}.
+
+@findex LOAD DATA INFILE
+@node LOAD DATA, UPDATE, REPLACE, Reference
+@section @code{LOAD DATA INFILE} syntax
+
+@example
+LOAD DATA [LOW_PRIORITY] [LOCAL] INFILE 'file_name.txt' [REPLACE | IGNORE]
+ INTO TABLE tbl_name
+ [FIELDS
+ [TERMINATED BY '\t']
+ [OPTIONALLY] ENCLOSED BY '']
+ [ESCAPED BY '\\' ]]
+ [LINES TERMINATED BY '\n']
+ [IGNORE number LINES]
+ [(col_name,...)]
+@end example
+
+The @code{LOAD DATA INFILE} statement reads rows from a text file into a
+table at a very high speed. If the @code{LOCAL} keyword is specified, the
+file is read from the client host. If @code{LOCAL} is not specified, the
+file must be located on the server. (@code{LOCAL} is available in
+@strong{MySQL} 3.22.6 or later.)
+
+For security reasons, when reading text files located on the server, the
+files must either reside in the database directory or be readable by all.
+Also, to use @code{LOAD DATA INFILE} on server files, you must have the
+@strong{file} privilege on the server host.
+@xref{Privileges provided}.
+
+If you specify the keyword @code{LOW_PRIORITY}, execution of the
+@code{LOAD DATA} statement is delayed until no other clients are reading
+from the table.
+
+Using @code{LOCAL} will be a bit slower than letting the server access the
+files directly, because the contents of the file must travel from the client
+host to the server host. On the other hand, you do not need the
+@strong{file} privilege to load local files.
+
+@cindex @code{mysqlimport}
+You can also load data files by using the @code{mysqlimport} utility; it
+operates by sending a @code{LOAD DATA INFILE} command to the server. The
+@code{--local} option causes @code{mysqlimport} to read data files from the
+client host. You can specify the @code{--compress} option to get better
+performance over slow networks if the client and server support the
+compressed protocol.
+
+When locating files on the server host, the server uses the following rules:
+
+@itemize @bullet
+@item
+If an absolute pathname is given, the server uses the pathname as is.
+
+@item
+If a relative pathname with one or more leading components is given,
+the server searches for the file relative to the server's data directory.
+
+@item
+If a filename with no leading components is given, the server looks for
+the file in the database directory of the current database.
+@end itemize
+
+Note that these rules mean a file given as @file{./myfile.txt} is read from
+the server's data directory, whereas a file given as @file{myfile.txt} is
+read from the database directory of the current database. For example,
+the following @code{LOAD DATA} statement reads the file @file{data.txt}
+from the database directory for @code{db1} because @code{db1} is the current
+database, even though the statement explicitly loads the file into a
+table in the @code{db2} database:
+
+@example
+mysql> USE db1;
+mysql> LOAD DATA INFILE "data.txt" INTO TABLE db2.my_table;
+@end example
+
+The @code{REPLACE} and @code{IGNORE} keywords control handling of input
+records that duplicate existing records on unique key values. If you specify
+@code{REPLACE}, new rows replace existing rows that have the same unique key
+value. If you specify @code{IGNORE}, input rows that duplicate an existing
+row on a unique key value are skipped. If you don't specify either option, an
+error occurs when a duplicate key value is found, and the rest of the text
+file is ignored.
+
+If you load data from a local file using the @code{LOCAL} keyword, the server
+has no way to stop transmission of the file in the middle of the operation,
+so the default bahavior is the same as if @code{IGNORE} is specified.
+
+@code{LOAD DATA INFILE} is the complement of @code{SELECT ... INTO OUTFILE}.
+@xref{SELECT, , @code{SELECT}}.
+To write data from a database to a file, use @code{SELECT ... INTO OUTFILE}.
+To read the file back into the database, use @code{LOAD DATA INFILE}.
+The syntax of the @code{FIELDS} and @code{LINES} clauses is the same for
+both commands. Both clauses are optional, but @code{FIELDS}
+must precede @code{LINES} if both are specified.
+
+If you specify a @code{FIELDS} clause,
+each of its subclauses (@code{TERMINATED BY}, @code{[OPTIONALLY] ENCLOSED
+BY} and @code{ESCAPED BY}) is also optional, except that you must
+specify at least one of them.
+
+If you don't specify a @code{FIELDS} clause, the defaults are the
+same as if you had written this:
+
+@example
+FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'
+@end example
+
+If you don't specify a @code{LINES} clause, the default
+is the same as if you had written this:
+
+@example
+LINES TERMINATED BY '\n'
+@end example
+
+In other words, the defaults cause @code{LOAD DATA INFILE} to act as follows
+when reading input:
+
+@itemize @bullet
+@item
+Look for line boundaries at newlines
+
+@item
+Break lines into fields at tabs
+
+@item
+Do not expect fields to be enclosed within any quoting characters
+
+@item
+Interpret occurrences of tab, newline or @samp{\} preceded by
+@samp{\} as literal characters that are part of field values
+@end itemize
+
+Conversely, the defaults cause @code{SELECT ... INTO OUTFILE} to act as
+follows when writing output:
+
+@itemize @bullet
+@item
+Write tabs between fields
+
+@item
+Do not enclose fields within any quoting characters
+
+@item
+Use @samp{\} to escape instances of tab, newline or @samp{\} that occur
+within field values
+
+@item
+Write newlines at the ends of lines
+@end itemize
+
+Note that to write @code{FIELDS ESCAPED BY '\\'}, you must specify two
+backslashes for the value to be read as a single backslash.
+
+The @code{IGNORE number LINES} option can be used to ignore a header of
+column names at the start of the file:
+
+@example
+mysql> LOAD DATA INFILE "/tmp/file_name" into table test IGNORE 1 LINES;
+@end example
+
+When you use @code{SELECT ... INTO OUTFILE} in tandem with @code{LOAD
+DATA INFILE} to write data from a database into a file and then read
+the file back into the database later, the field and line handling
+options for both commands must match. Otherwise, @code{LOAD DATA
+INFILE} will not interpret the contents of the file properly. Suppose
+you use @code{SELECT ... INTO OUTFILE} to write a file with
+fields delimited by commas:
+
+@example
+mysql> SELECT * INTO OUTFILE 'data.txt'
+ FIELDS TERMINATED BY ','
+ FROM ...
+@end example
+
+To read the comma-delimited file back in, the correct statement would be:
+
+@example
+mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
+ FIELDS TERMINATED BY ',';
+@end example
+
+If instead you tried to read in the file with the statement shown below, it
+wouldn't work because it instructs @code{LOAD DATA INFILE} to look for
+tabs between fields:
+
+@example
+mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2
+ FIELDS TERMINATED BY '\t';
+@end example
+
+The likely result is that each input line would be interpreted as
+a single field.
+
+@code{LOAD DATA INFILE} can be used to read files obtained from
+external sources, too. For example, a file in dBASE format will have
+fields separated by commas and enclosed in double quotes. If lines in
+the file are terminated by newlines, the command shown below
+illustrates the field and line handling options you would use to load
+the file:
+
+@example
+mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
+ FIELDS TERMINATED BY ',' ENCLOSED BY '"'
+ LINES TERMINATED BY '\n';
+@end example
+
+Any of the field or line handling options may specify an empty string
+(@code{''}). If not empty, the @code{FIELDS [OPTIONALLY] ENCLOSED BY}
+and @code{FIELDS ESCAPED BY} values must be a single character. The
+@code{FIELDS TERMINATED BY} and @code{LINES TERMINATED BY} values may
+be more than one character. For example, to write lines that are
+terminated by carriage return-linefeed pairs, or to read a file
+containing such lines, specify a @code{LINES TERMINATED BY '\r\n'}
+clause.
+
+@code{FIELDS [OPTIONALLY] ENCLOSED BY} controls quoting of fields. For
+output (@code{SELECT ... INTO OUTFILE}), if you omit the word
+@code{OPTIONALLY}, all fields are enclosed by the @code{ENCLOSED BY}
+character. An example of such output (using a comma as the field
+delimiter) is shown below:
+
+@example
+"1","a string","100.20"
+"2","a string containing a , comma","102.20"
+"3","a string containing a \" quote","102.20"
+"4","a string containing a \", quote and comma","102.20"
+@end example
+
+If you specify @code{OPTIONALLY}, the @code{ENCLOSED BY} character is
+used only to enclose @code{CHAR} and @code{VARCHAR} fields:
+
+@example
+1,"a string",100.20
+2,"a string containing a , comma",102.20
+3,"a string containing a \" quote",102.20
+4,"a string containing a \", quote and comma",102.20
+@end example
+
+Note that occurrences of the @code{ENCLOSED BY} character within a
+field value are escaped by prefixing them with the @code{ESCAPED BY}
+character. Also note that if you specify an empty @code{ESCAPED BY}
+value, it is possible to generate output that cannot be read properly by
+@code{LOAD DATA INFILE}. For example, the output just shown above would
+appear as shown below if the escape character is empty. Observe that the
+second field in the fourth line contains a comma following the quote, which
+(erroneously) appears to terminate the field:
+
+@example
+1,"a string",100.20
+2,"a string containing a , comma",102.20
+3,"a string containing a " quote",102.20
+4,"a string containing a ", quote and comma",102.20
+@end example
+
+For input, the @code{ENCLOSED BY} character, if present, is stripped from the
+ends of field values. (This is true whether or not @code{OPTIONALLY} is
+specified; @code{OPTIONALLY} has no effect on input interpretation.)
+Occurrences of the @code{ENCLOSED BY} character preceded by the
+@code{ESCAPED BY} character are interpreted as part of the current field
+value. In addition, duplicated @code{ENCLOSED BY} characters occurring
+within fields are interpreted as single @code{ENCLOSED BY} characters if the
+field itself starts with that character. For example, if @code{ENCLOSED BY
+'"'} is specified, quotes are handled as shown below:
+
+@example
+"The ""BIG"" boss" -> The "BIG" boss
+The "BIG" boss -> The "BIG" boss
+The ""BIG"" boss -> The ""BIG"" boss
+@end example
+
+@code{FIELDS ESCAPED BY} controls how to write or read special characters.
+If the @code{FIELDS ESCAPED BY} character is not empty, it is used to prefix
+the following characters on output:
+@itemize @bullet
+@item
+The @code{FIELDS ESCAPED BY} character
+@item
+The @code{FIELDS [OPTIONALLY] ENCLOSED BY} character
+@item
+The first character of the @code{FIELDS TERMINATED BY} and
+@code{LINES TERMINATED BY} values
+@item
+ASCII @code{0} (what is actually written following the escape character is
+ASCII @code{'0'}, not a zero-valued byte)
+@end itemize
+
+If the @code{FIELDS ESCAPED BY} character is empty, no characters are escaped.
+It is probably not a good idea to specify an empty escape character,
+particularly if field values in your data contain any of the characters in
+the list just given.
+
+For input, if the @code{FIELDS ESCAPED BY} character is not empty, occurrences
+of that character are stripped and the following character is taken literally
+as part of a field value. The exceptions are an escaped @samp{0} or
+@samp{N} (e.g., @code{\0} or @code{\N} if the escape character is
+@samp{\}). These sequences are interpreted as ASCII @code{0} (a zero-valued
+byte) and @code{NULL}. See below for the rules on @code{NULL} handling.
+
+For more information about @samp{\}-escape syntax,
+see @ref{Literals}.
+
+In certain cases, field and line handling options interact:
+
+@itemize @bullet
+@item
+If @code{LINES TERMINATED BY} is an empty string and @code{FIELDS
+TERMINATED BY} is non-empty, lines are also terminated with
+@code{FIELDS TERMINATED BY}.
+@item
+If the @code{FIELDS TERMINATED BY} and @code{FIELDS ENCLOSED BY} values are
+both empty (@code{''}), a fixed-row (non-delimited) format is used. With
+fixed-row format, no delimiters are used between fields. Instead, column
+values are written and read using the ``display'' widths of the columns. For
+example, if a column is declared as @code{INT(7)}, values for the column are
+written using 7-character fields. On input, values for the column are
+obtained by reading 7 characters. Fixed-row format also affects handling of
+@code{NULL} values; see below. Note that fixed size format will not work
+if you are using a multi-byte character set.
+@end itemize
+
+Handling of @code{NULL} values varies, depending on the @code{FIELDS} and
+@code{LINES} options you use:
+
+@itemize @bullet
+@item
+For the default @code{FIELDS} and @code{LINES} values,
+@code{NULL} is written as @code{\N} for output and @code{\N} is read
+as @code{NULL} for input (assuming the @code{ESCAPED BY} character
+is @samp{\}).
+
+@item
+If @code{FIELDS ENCLOSED BY} is not empty, a field containing the literal
+word @code{NULL} as its value is read as a @code{NULL} value (this differs
+from the word @code{NULL} enclosed within @code{FIELDS ENCLOSED BY}
+characters, which is read as the string @code{'NULL'}).
+
+@item
+If @code{FIELDS ESCAPED BY} is empty, @code{NULL} is written as the word
+@code{NULL}.
+
+@item
+With fixed-row format (which happens when @code{FIELDS TERMINATED BY} and
+@code{FIELDS ENCLOSED BY} are both empty), @code{NULL} is written as an empty
+string. Note that this causes both @code{NULL} values and empty strings in
+the table to be indistinguishable when written to the file because they are
+both written as empty strings. If you need to be able to tell the two apart
+when reading the file back in, you should not use fixed-row format.
+@end itemize
+
+Some cases are not supported by @code{LOAD DATA INFILE}:
+@itemize @bullet
+
+@item
+Fixed-size rows (@code{FIELDS TERMINATED BY} and @code{FIELDS ENCLOSED
+BY} both empty) and @code{BLOB} or @code{TEXT} columns.
+
+@item
+If you specify one separator that is the same as or a prefix of another,
+@code{LOAD DATA INFILE} won't be able to interpret the input properly.
+For example, the following @code{FIELDS} clause would cause problems:
+
+@example
+FIELDS TERMINATED BY '"' ENCLOSED BY '"'
+@end example
+
+@item
+If @code{FIELDS ESCAPED BY} is empty, a field value that contains an occurrence
+of @code{FIELDS ENCLOSED BY} or @code{LINES TERMINATED BY}
+followed by the @code{FIELDS TERMINATED BY} value will cause @code{LOAD
+DATA INFILE} to stop reading a field or line too early.
+This happens because @code{LOAD DATA INFILE} cannot properly determine
+where the field or line value ends.
+@end itemize
+
+The following example loads all columns of the @code{persondata} table:
+
+@example
+mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;
+@end example
+
+No field list is specified, so @code{LOAD DATA INFILE} expects input rows
+to contain a field for each table column. The default @code{FIELDS} and
+@code{LINES} values are used.
+
+If you wish to load only some of a table's columns, specify a field list:
+
+@example
+mysql> LOAD DATA INFILE 'persondata.txt'
+ INTO TABLE persondata (col1,col2,...);
+@end example
+
+You must also specify a field list if the order of the fields in the input
+file differs from the order of the columns in the table. Otherwise,
+@strong{MySQL} cannot tell how to match up input fields with table columns.
+
+If a row has too few fields, the columns for which no input field is present
+are set to default values. Default value assignment is described in
+@ref{CREATE TABLE, , @code{CREATE TABLE}}.
+
+An empty field value is interpreted differently than if the field value
+is missing:
+
+@itemize @bullet
+@item
+For string types, the column is set to the empty string.
+
+@item
+For numeric types, the column is set to @code{0}.
+
+@item
+For date and time types, the column is set to the appropriate ``zero''
+value for the type.
+@xref{Date and time types}.
+@end itemize
+
+@code{TIMESTAMP} columns are only set to the current date and time if there
+is a @code{NULL} value for the column, or (for the first @code{TIMESTAMP}
+column only) if the @code{TIMESTAMP} column is left out from the field list
+when a field list is specified.
+
+If an input row has too many fields, the extra fields are ignored and
+the number of warnings is incremented.
+
+@code{LOAD DATA INFILE} regards all input as strings, so you can't use
+numeric values for @code{ENUM} or @code{SET} columns the way you can with
+@code{INSERT} statements. All @code{ENUM} and @code{SET} values must be
+specified as strings!
+
+@findex mysql_info()
+If you are using the C API, you can get information about the query by
+calling the API function @code{mysql_info()} when the @code{LOAD DATA INFILE}
+query finishes. The format of the information string is shown below:
+
+@example
+Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
+@end example
+
+Warnings occur under the same circumstances as when values are inserted
+via the @code{INSERT} statement (@pxref{INSERT, , @code{INSERT}}), except
+that @code{LOAD DATA INFILE} also generates warnings when there are too few
+or too many fields in the input row. The warnings are not stored anywhere;
+the number of warnings can only be used as an indication if everything went
+well. If you get warnings and want to know exactly why you got them, one way
+to do this is to use @code{SELECT ... INTO OUTFILE} into another file and
+compare this to your original input file.
+
+If you need @code{LOAD DATA INFILE} to read from a pipe, you can use the
+following trick:
+
+@example
+mkfifo /mysql/db/x/x
+chmod 666 /mysql/db/x/x
+cat < /dev/tcp/10.1.1.12/4711 > /nt/mysql/db/x/x
+mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x
+@end example
+
+For more information about the efficiency of @code{INSERT} versus
+@code{LOAD DATA INFILE} and speeding up @code{LOAD DATA INFILE},
+@xref{Insert speed}.
+
+@findex UPDATE
+@node UPDATE, USE, LOAD DATA, Reference
+@section @code{UPDATE} syntax
+
+@example
+UPDATE [LOW_PRIORITY] [IGNORE] tbl_name SET col_name1=expr1,col_name2=expr2,...
+ [WHERE where_definition] [LIMIT #]
+@end example
+
+@code{UPDATE} updates columns in existing table rows with new values. The
+@code{SET} clause indicates which columns to modify and the values they
+should be given. The @code{WHERE} clause, if given, specifies which rows
+should be updated. Otherwise all rows are updated.
+
+If you specify the keyword @code{LOW_PRIORITY}, execution of the
+@code{UPDATE} is delayed until no other clients are reading from the table.
+
+If you specify the keyword @code{IGNORE}, the update statement will not
+abort even if we get duplicate key errors during the update. Rows that
+would cause conflicts will not be updated.
+
+If you access a column from @code{tbl_name} in an expression,
+@code{UPDATE} uses the current value of the column. For example, the
+following statement sets the @code{age} column to one more than its
+current value:
+
+@example
+mysql> UPDATE persondata SET age=age+1;
+@end example
+
+@code{UPDATE} assignments are evaluated from left to right. For example, the
+following statement doubles the @code{age} column, then increments it:
+
+@example
+mysql> UPDATE persondata SET age=age*2, age=age+1;
+@end example
+
+If you set a column to the value it currently has, @strong{MySQL} notices
+this and doesn't update it.
+
+@findex mysql_info()
+@code{UPDATE} returns the number of rows that were actually changed.
+In @strong{MySQL} 3.22 or later, the C API function @code{mysql_info()}
+returns the number of rows that were matched and updated and the number of
+warnings that occurred during the @code{UPDATE}.
+
+In @strong{MySQL} 3.23 you can use @code{LIMIT #} to ensure that only a given
+number of rows are changed.
+
+@findex USE
+@node USE, FLUSH, UPDATE, Reference
+@section @code{USE} syntax
+
+@example
+USE db_name
+@end example
+
+The @code{USE db_name} statement tells @strong{MySQL} to use the @code{db_name}
+database as the default database for subsequent queries. The database remains
+current until the end of the session, or until another @code{USE} statement
+is issued:
+
+@example
+mysql> USE db1;
+mysql> SELECT count(*) FROM mytable; # selects from db1.mytable
+mysql> USE db2;
+mysql> SELECT count(*) FROM mytable; # selects from db2.mytable
+@end example
+
+Making a particular database current by means of the @code{USE} statement
+does not preclude you from accessing tables in other databases. The example
+below accesses the @code{author} table from the @code{db1} database and the
+@code{editor} table from the @code{db2} database:
+
+@example
+mysql> USE db1;
+mysql> SELECT author_name,editor_name FROM author,db2.editor
+ WHERE author.editor_id = db2.editor.editor_id;
+@end example
+
+@cindex Sybase compatibility
+@cindex Compatibility, with Sybase
+The @code{USE} statement is provided for Sybase compatibility.
+
+@cindex @code{mysqladmin}
+@findex FLUSH
+@node FLUSH, KILL, USE, Reference
+@section @code{FLUSH} syntax (clearing caches)
+
+@example
+FLUSH flush_option [,flush_option]
+@end example
+
+You should use the @code{FLUSH} command if you want to clear some of the
+internal caches @strong{MySQL} uses. To execute @code{FLUSH}, you must have
+the @strong{reload} privilege.
+
+@code{flush_option} can be any of the following:
+
+@multitable @columnfractions .15 .85
+@item @code{HOSTS} @tab Empties the host cache tables. You should flush the
+host tables if some of your hosts change IP number or if you get the
+error message @code{Host ... is blocked}. When more than
+@code{max_connect_errors} errors occur in a row for a given host while
+connection to the @strong{MySQL} server, @strong{MySQL} assumes
+something is wrong and blocks the host from further connection requests.
+Flushing the host tables allows the host to attempt to connect
+again. @xref{Blocked host}.) You can start @code{mysqld} with
+@code{-O max_connection_errors=999999999} to avoid this error message.
+
+@item @code{LOGS} @tab Closes and reopens the standard and update log
+files. If you have specified the update log file without an extension,
+the extension number of the new update log file will be incremented by
+one relative to the previous file. If you have used an extension in the
+file name, @strong{MySQL} will close and reopen the update log file.
+@xref{Update log}.
+
+@item @code{PRIVILEGES} @tab Reloads the privileges from the grant tables in
+the @code{mysql} database.
+
+@item @code{TABLES} @tab Closes all open tables.
+
+@item @code{TABLES WITH READ LOCK} @tab Closes all open tables and locks all tables for all databases with a read until one executes @code{UNLOCK TABLES}.
+
+@item @code{STATUS} @tab Resets most status variables to zero.
+@end multitable
+
+You can also access each of the commands shown above with the @code{mysqladmin}
+utility, using the @code{flush-hosts}, @code{flush-logs}, @code{reload}
+or @code{flush-tables} commands.
+
+@cindex @code{mysqladmin}
+@findex KILL
+@node KILL, SHOW, FLUSH, Reference
+@section @code{KILL} syntax
+
+@example
+KILL thread_id
+@end example
+
+Each connection to @code{mysqld} runs in a separate thread. You can see
+which threads are running with the @code{SHOW PROCESSLIST} command, and kill
+a thread with the @code{KILL thread_id} command.
+
+If you have the @strong{process} privilege, you can see and kill all threads.
+Otherwise, you can see and kill only your own threads.
+
+You can also use the @code{mysqladmin processlist} and @code{mysqladmin kill}
+commands to examine and kill threads.
+
+@findex SHOW DATABASES
+@findex SHOW TABLES
+@findex SHOW COLUMNS
+@findex SHOW FIELDS
+@findex SHOW INDEX
+@findex SHOW KEYS
+@findex SHOW STATUS
+@findex SHOW VARIABLES
+@findex SHOW PROCESSLIST
+@findex SHOW TABLE STATUS
+@findex SHOW GRANTS
+@node SHOW, EXPLAIN, KILL, Reference
+@section @code{SHOW} syntax (Get information about tables, columns,...)
+
+@example
+ SHOW DATABASES [LIKE wild]
+or SHOW TABLES [FROM db_name] [LIKE wild]
+or SHOW COLUMNS FROM tbl_name [FROM db_name] [LIKE wild]
+or SHOW INDEX FROM tbl_name [FROM db_name]
+or SHOW TABLE STATUS [FROM db_name] [LIKE wild]
+or SHOW STATUS [LIKE wild]
+or SHOW VARIABLES [LIKE wild]
+or SHOW [FULL] PROCESSLIST
+or SHOW GRANTS FOR user
+@end example
+
+@code{SHOW} provides information about databases, tables, columns or
+status information about the server. If the @code{LIKE wild} part is
+used, the @code{wild} string can be a string that uses the SQL @samp{%}
+and @samp{_} wildcard characters.
+
+@findex SHOW DATABASES
+@findex SHOW TABLES
+@findex SHOW COLUMNS
+@findex SHOW FIELDS
+@findex SHOW INDEX
+@findex SHOW KEYS
+@menu
+* SHOW DATABASE INFO::
+* SHOW TABLE STATUS::
+* SHOW STATUS::
+* SHOW VARIABLES::
+* SHOW PROCESSLIST::
+* SHOW GRANTS::
+@end menu
+
+@node SHOW DATABASE INFO, SHOW TABLE STATUS, SHOW, SHOW
+@subsection SHOW information about database, tables, columns and index
+
+You can use @code{db_name.tbl_name} as an alternative to the @code{tbl_name
+FROM db_name} syntax. These two statements are equivalent:
+
+@example
+mysql> SHOW INDEX FROM mytable FROM mydb;
+mysql> SHOW INDEX FROM mydb.mytable;
+@end example
+
+@code{SHOW DATABASES} lists the databases on the @strong{MySQL} server
+host. You can also get this list using the @code{mysqlshow} command.
+
+@code{SHOW TABLES} lists the tables in a given database. You can also
+get this list using the @code{mysqlshow db_name} command.
+
+@strong{Note:} If a user doesn't have any privileges for a table, the table
+will not show up in the output from @code{SHOW TABLES} or @code{mysqlshow
+db_name}.
+
+@code{SHOW COLUMNS} lists the columns in a given table. If the column
+types are different than you expect them to be based on a @code{CREATE
+TABLE} statement, note that @strong{MySQL} sometimes changes column
+types. @xref{Silent column changes}.
+
+The @code{DESCRIBE} statement provides information similar to
+@code{SHOW COLUMNS}.
+@xref{DESCRIBE, , @code{DESCRIBE}}.
+
+@code{SHOW FIELDS} is a synonym for @code{SHOW COLUMNS} and
+@code{SHOW KEYS} is a synonym for @code{SHOW INDEX}. You can also
+list a table's columns or indexes with @code{mysqlshow db_name tbl_name}
+or @code{mysqlshow -k db_name tbl_name}.
+
+@code{SHOW INDEX} returns the index information in a format that closely
+resembles the @code{SQLStatistics} call in ODBC. The following columns
+are returned:
+
+@multitable @columnfractions .35 .65
+@item @strong{Column} @tab @strong{Meaning}
+@item @code{Table} @tab Name of the table
+@item @code{Non_unique} @tab 0 if the index can't contain duplicates.
+@item @code{Key_name} @tab Name of the index
+@item @code{Seq_in_index} @tab Column sequence number in index, starting with 1.
+@item @code{Column_name} @tab Column name.
+@item @code{Collation} @tab How the column is sorted in the index. In
+@strong{MySQL}, this can have values @code{A} (Ascending) or @code{NULL}
+(Not sorted).
+@item @code{Cardinality} @tab Number of unique values in the index.
+This is updated by running @code{isamchk -a}.
+@item @code{Sub_part} @tab Number of indexed characters if the column is
+only partly indexed. @code{NULL} if the entire key is indexed.
+@end multitable
+
+@node SHOW TABLE STATUS, SHOW STATUS, SHOW DATABASE INFO, SHOW
+@subsection SHOW status information about tables
+
+@code{SHOW TABLE STATUS} (new in version 3.23) works likes @code{SHOW
+STATUS}, but provides a lot of information about each table. You can
+also get this list using the @code{mysqlshow --status db_name} command.
+The following columns are returned:
+
+@multitable @columnfractions .30 .70
+@item @strong{Column} @tab @strong{Meaning}
+@item @code{Name} @tab Name of the table
+@item @code{Type} @tab Type of table (BDB, ISAM, MyISAM or HEAP)
+@item @code{Row_format} @tab The row storage format (Fixed, Dynamic, or Compressed)
+@item @code{Rows} @tab Number of rows
+@item @code{Avg_row_length} @tab Average row length
+@item @code{Data_length} @tab Length of the data file
+@item @code{Max_data_length} @tab Max length of the data file
+@item @code{Index_length} @tab Length of the index file
+@item @code{Data_free} @tab Number of allocated but not used bytes
+@item @code{Auto_increment} @tab Next autoincrement value
+@item @code{Create_time} @tab When the table was created
+@item @code{Update_time} @tab When the data file was last updated
+@item @code{Check_time} @tab When one last run a check on the table
+@item @code{Create_options} @tab Extra options used with @code{CREATE TABLE}
+@item @code{Comment} @tab The comment used when creating the table (or some information why @strong{MySQL} couldn't access the table information).
+@end multitable
+
+@node SHOW STATUS, SHOW VARIABLES, SHOW TABLE STATUS, SHOW
+@subsection SHOW status information
+
+@cindex @code{mysqladmin}
+@code{SHOW STATUS} provides server status information
+(like @code{mysqladmin extended-status}). The output resembles that shown
+below, though the format and numbers probably differ:
+
+@example
++--------------------------+-------+
+| Variable_name | Value |
++--------------------------+-------+
+| Aborted_clients | 0 |
+| Aborted_connects | 0 |
+| Bytes_received | 100 |
+| Bytes_sent | 2106 |
+| Connections | 4 |
+| Created_tmp_tables | 0 |
+| Delayed_insert_threads | 0 |
+| Delayed_writes | 0 |
+| Delayed_errors | 0 |
+| Flush_commands | 1 |
+| Handler_delete | 0 |
+| Handler_read_first | 1 |
+| Handler_read_key | 0 |
+| Handler_read_next | 2 |
+| Handler_read_prev | 0 |
+| Handler_read_rnd | 0 |
+| Handler_read_rnd_next | 25 |
+| Handler_update | 0 |
+| Handler_write | 0 |
+| Key_blocks_used | 1 |
+| Key_read_requests | 2 |
+| Key_reads | 1 |
+| Key_write_requests | 0 |
+| Key_writes | 0 |
+| Max_used_connections | 0 |
+| Not_flushed_key_blocks | 0 |
+| Not_flushed_delayed_rows | 0 |
+| Open_tables | 0 |
+| Open_files | 0 |
+| Open_streams | 0 |
+| Opened_tables | 6 |
+| Questions | 4 |
+| Slow_launch_threads | 0 |
+| Slow_queries | 0 |
+| Slave_running | OFF |
+| Threads_cached | 0 |
+| Threads_connected | 1 |
+| Threads_running | 1 |
+| Uptime | 1256 |
++--------------------------+-------+
+
+@end example
+
+The status variables listed above have the following meaning:
+
+@multitable @columnfractions .35 .65
+@item @code{Aborted_clients} @tab Number of connections that has been aborted because the client has died without closing the connection properly.
+@item @code{Aborted_connects} @tab Number of tries to connect to the @strong{MySQL} server that has failed.
+@item @code{Bytes_received} @tab Number of bytes received from the client
+@item @code{Bytes_sent} @tab Number of bytes received from the client
+@item @code{Connections} @tab Number of connection attempts to the @strong{MySQL} server.
+@item @code{Created_tmp_tables} @tab Number of implicit temporary tables that has been created while executing statements.
+@item @code{Delayed_insert_threads} @tab Number of delayed insert handler threads in use.
+@item @code{Delayed_writes} @tab Number of rows written with @code{INSERT DELAYED}.
+@item @code{Delayed_errors} @tab Number of rows written with @code{INSERT DELAYED} for which some error occurred (probably @code{duplicate key}).
+@item @code{Flush_commands} @tab Number of executed @code{FLUSH} commands.
+@item @code{Handler_delete} @tab Number of times a row was deleted from a table.
+@item @code{Handler_read_first} @tab Number of times the first entry was read from an index.
+If this is high, it suggests that the server is doing a lot of full index scans, for example,
+@code{SELECT col1 FROM foo}, assuming that col1 is indexed
+@item @code{Handler_read_key} @tab Number of requests to read a row based on a key. If this
+is high, it is a good indication that your queries and tables are properly indexed.
+@item @code{Handler_read_next} @tab Number of requests to read next row in key order. This
+will be incremented if you are querying an index column with a range contraint. This also
+will be incremented if you are doing an index scan.
+@item @code{Handler_read_rnd} @tab Number of requests to read a row based on a fixed position.
+This will be high if you are doing a lot of queries that require sorting of the result.
+@item @code{Handler_read_rnd_next} @tab Number of requests to read the next row in the datafile.
+This will be high if you are doing a lot of table scans - generally this suggests that you tables
+are not properly indexed or that you queries are not written to take advantaged of the indeces you
+have..
+@item @code{Handler_update} @tab Number of requests to update a row in a table.
+@item @code{Handler_write} @tab Number of requests to insert a row in a table.
+@item @code{Key_blocks_used} @tab The number of used blocks in the key cache.
+@item @code{Key_read_requests} @tab The number of requests to read a key block from the cache.
+@item @code{Key_reads} @tab The number of physical reads of a key block from disk.
+@item @code{Key_write_requests} @tab The number of requests to write a key block to the cache.
+@item @code{Key_writes} @tab The number of physical writes of a key block to disk.
+@item @code{Max_used_connections} @tab The maximum number of connections that has been in use simultaneously.
+@item @code{Not_flushed_key_blocks} @tab Keys blocks in the key cache that has changed but hasn't yet been flushed to disk.
+@item @code{Not_flushed_delayed_rows} @tab Number of rows waiting to be written in @code{INSERT DELAY} queues.
+@item @code{Open_tables} @tab Number of tables that are open.
+@item @code{Open_files} @tab Number of files that are open.
+@item @code{Open_streams} @tab Number of streams that are open (used mainly for logging)
+@item @code{Opened_tables} @tab Number of tables that has been opened.
+@item @code{Questions} @tab Number of queries sent to the server.
+@item @code{Slow_launch_threads} @tab Number of threads that has taken more than @code{slow_launch_time} to connect.
+@item @code{Slow_queries} @tab Number of queries that has taken more than @code{long_query_time}
+@item @code{Threads_cached} @tab Number of threads in the thread cache.
+@item @code{Threads_connected} @tab Number of currently open connections.
+@item @code{Threads_running} @tab Number of threads that are not sleeping.
+@item @code{Uptime} @tab How many seconds the server has been up.
+@end multitable
+
+Some comments about the above:
+
+@itemize @bullet
+@item
+If @code{Opened_tables} is big, then your @code{table_cache}
+variable is probably too small.
+@item
+If @code{key_reads} is big, then your @code{key_cache} is probably too
+small. The cache hit rate can be calculated with
+@code{key_reads}/@code{key_read_requests}.
+@item
+If @code{Handler_read_rnd} is big, then you have a probably a lot of queries
+that requires @strong{MySQL} to scan whole tables or you have joins that doesn't use
+keys properly.
+@end itemize
+
+@node SHOW VARIABLES, SHOW PROCESSLIST, SHOW STATUS, SHOW
+@subsection SHOW VARIABLES
+
+@code{SHOW VARIABLES} shows the values of the some of @strong{MySQL} system
+variables. You can also get this information using the @code{mysqladmin
+variables} command. If the default values are unsuitable, you can set most
+of these variables using command-line options when @code{mysqld} starts up.
+@xref{Command-line options}.
+
+The output resembles that shown below, though the format and numbers may
+differ somewhat:
+
+@example
++----------------------------+------------------------------+
+| Variable_name | Value |
++----------------------------+------------------------------+
+| ansi_mode | OFF |
+| back_log | 50 |
+| basedir | /usr/local/mysql/ |
+| bdb_cache_size | 1048540 |
+| bdb_home | /usr/local/mysql/data/ |
+| bdb_logdir | |
+| bdb_tmpdir | /tmp/ |
+| character_set | latin1 |
+| character_sets | latin1 |
+| connect_timeout | 5 |
+| concurrent_insert | ON |
+| datadir | /usr/local/mysql/data/ |
+| delay_key_write | ON |
+| delayed_insert_limit | 100 |
+| delayed_insert_timeout | 300 |
+| delayed_queue_size | 1000 |
+| join_buffer_size | 131072 |
+| flush | OFF |
+| flush_time | 0 |
+| init_file | |
+| interactive_timeout | 28800 |
+| key_buffer_size | 16776192 |
+| language | /usr/local/mysql/share/english/ |
+| log | OFF |
+| log_update | OFF |
+| log_bin | OFF |
+| log_slave_updates | OFF |
+| long_query_time | 10 |
+| low_priority_updates | OFF |
+| lower_case_table_names | 0 |
+| max_allowed_packet | 1047552 |
+| max_connections | 100 |
+| max_connect_errors | 10 |
+| max_delayed_threads | 20 |
+| max_heap_table_size | 16777216 |
+| max_join_size | 4294967295 |
+| max_sort_length | 1024 |
+| max_tmp_tables | 32 |
+| max_write_lock_count | 4294967295 |
+| myisam_sort_buffer_size | 8388608 |
+| net_buffer_length | 16384 |
+| net_retry_count | 10 |
+| pid_file | /usr/local/mysql/data/tik.pid |
+| port | 3306 |
+| protocol_version | 10 |
+| record_buffer | 131072 |
+| skip_locking | ON |
+| skip_networking | OFF |
+| skip_show_database | OFF |
+| slow_launch_time | 2 |
+| socket | /tmp/mysql.sock |
+| sort_buffer | 2097116 |
+| table_cache | 64 |
+| table_type | MYISAM |
+| thread_stack | 131072 |
+| thread_cache_size | 3 |
+| tmp_table_size | 1048576 |
+| tmpdir | /tmp/ |
+| version | 3.23.21-beta-debug |
+| wait_timeout | 28800 |
++-----------------------------------+-----------------------+
+@end example
+
+Each option is described below. Values for buffer sizes, lengths and stack
+sizes are given in bytes. You can specify values with a suffix of @samp{K}
+or @samp{M} to indicate kilobytes or megabytes. For example, @code{16M}
+indicates 16 megabytes. The case of suffix letters does not matter;
+@code{16M} and @code{16m} are equivalent.
+
+@table @code
+@item @code{ansi_mode}.
+Is @code{ON} if @code{mysqld} was started with @code{--ansi}.
+@xref{Ansi mode}.
+
+@item @code{back_log}
+The number of outstanding connection requests @strong{MySQL} can have. This
+comes into play when the main @strong{MySQL} thread gets @strong{VERY}
+many connection requests in a very short time. It then takes some time
+(although very little) for the main thread to check the connection and start
+a new thread. The @code{back_log} value indicates how many requests can be
+stacked during this short time before @strong{MySQL} momentarily stops
+answering new requests. You need to increase this only if you expect a large
+number of connections in a short period of time.
+
+In other words, this value is the size of the listen queue for incoming
+TCP/IP connections. Your operating system has its own limit on the size
+of this queue. The manual page for the Unix @code{listen(2)} system
+call should have more details. Check your OS documentation for the
+maximum value for this variable. Attempting to set @code{back_log}
+higher than your operating system limit will be ineffective.
+
+@item @code{bdb_cache_size}
+The buffer that is allocated to cache index and rows for @code{BDB} tables.
+If you don't use @code{BDB} tables, you should set this to 0 or
+start @code{mysqld} with @code{--skip-bdb} o not waste memory for this cache.
+
+@item @code{concurrent_inserts}
+If @code{ON} (the default), @code{MySQL} will allow you to use @code{INSERT}
+on @code{MyISAM} tables at the same time as you run @code{SELECT} queries
+on them. You can turn this option off by starting mysqld with @code{--safe}
+or @code{--skip-new}.
+
+@item @code{connect_timeout}
+The number of seconds the @code{mysqld} server is waiting for a connect
+packet before responding with @code{Bad handshake}.
+
+@item @code{delayed_insert_timeout}
+How long a @code{INSERT DELAYED} thread should wait for @code{INSERT}
+statements before terminating.
+
+@item @code{delayed_insert_limit}
+After inserting @code{delayed_insert_limit} rows, the @code{INSERT
+DELAYED} handler will check if there are any @code{SELECT} statements
+pending. If so, it allows these to execute before continuing.
+
+@item @code{delay_key_write}
+If enabled (is on by default), @strong{MySQL} will honor the
+@code{delay_key_write} option @code{CREATE TABLE}. This means that the
+key buffer for tables with this option will not get flushed on every
+index update, but only when a table is closed. This will speed up
+writes on keys a lot but you should add automatic checking of all tables
+with @code{myisamchk --fast --force} if you use this. Note that if you
+start @code{mysqld} with the @code{--delay-key-write-for-all-tables}
+option this means that all tables will be treated as if they were
+created with the @code{delay_key_write} option. You can clear this flag
+by starting @code{mysqld} with @code{--skip-new} or @code{--safe-mode}.
+
+@item @code{delayed_queue_size}
+What size queue (in rows) should be allocated for handling @code{INSERT
+DELAYED}. If the queue becomes full, any client that does @code{INSERT
+DELAYED} will wait until there is room in the queue again.
+
+@item @code{flush}
+This is @code{ON} if you have started @strong{MySQL} with the @code{--flush}
+option.
+
+@item @code{flush_time}
+If this is set to a non-zero value, then every @code{flush_time} seconds all
+tables will be closed (to free up resources and sync things to disk). We
+only recommend this option on Win95, Win98 or on system where you have
+very little resources.
+
+@item @code{init_file}
+The name of the file specified with the @code{--init-file} option when
+you start the server. This is a file of SQL statements you want the
+server to execute when it starts.
+
+@item @code{interactive_timeout}
+The number of seconds the server waits for activity on an interactive
+connection before closing it. An interactive client is defined as a
+client that uses the @code{CLIENT_INTERACTIVE} option to
+@code{mysql_real_connect()}. See also @code{wait_timeout}.
+
+@item @code{join_buffer_size}
+The size of the buffer that is used for full joins (joins that do not
+use indexes). The buffer is allocated one time for each full join
+between two tables. Increase this value to get a faster full join when
+adding indexes is not possible. (Normally the best way to get fast joins
+is to add indexes.)
+
+@c Make texi2html support index @anchor{Index cache size}. Then change
+@c some xrefs to point here
+@item @code{key_buffer_size}
+Index blocks are buffered and are shared by all threads.
+@code{key_buffer_size} is the size of the buffer used for index blocks.
+
+Increase this to get better index handling (for all reads and multiple
+writes) to as much as you can afford; 64M on a 256M machine that mainly
+runs @strong{MySQL} is quite common. If you however make this too big
+(more than 50% of your total memory?) your system may start to page and
+become REALLY slow. Remember that because @strong{MySQL} does not cache
+data read, that you will have to leave some room for the OS filesystem
+cache.
+
+You can check the performance of the key buffer by doing @code{show
+status} and examine the variables @code{Key_read_requests},
+@code{Key_reads}, @code{Key_write_requests} and @code{Key_writes}. The
+@code{Key_reads/Key_read_request} ratio should normally be < 0.01.
+The @code{Key_write/Key_write_requests} is usually near 1 if you are
+using mostly updates/deletes but may be much smaller if you tend to
+do updates that affect many at the same time or if you are
+using @code{delay_key_write}. @xref{SHOW}.
+
+To get even more speed when writing many rows at the same time use
+@code{LOCK TABLES}. @xref{LOCK TABLES, , @code{LOCK TABLES}}.
+
+@item @code{lower_case_table_names}
+Change all table names to lower case on disk.
+
+@item @code{long_query_time}
+If a query takes longer than this (in seconds), the @code{Slow_queries} counter
+will be incremented.
+
+@item @code{max_allowed_packet}
+The maximum size of one packet. The message buffer is initialized to
+@code{net_buffer_length} bytes, but can grow up to @code{max_allowed_packet}
+bytes when needed. This value by default is small, to catch big (possibly
+wrong) packets. You must increase this value if you are using big
+@code{BLOB} columns. It should be as big as the biggest @code{BLOB} you want
+to use.
+
+@item @code{max_connections}
+The number of simultaneous clients allowed. Increasing this value increases
+the number of file descriptors that @code{mysqld} requires. See below for
+comments on file descriptor limits. @xref{Too many connections}.
+
+@item @code{max_connect_errors}
+If there is more than this number of interrupted connections from a host
+this host will be blocked from further connections. You can unblock a host
+with the command @code{FLUSH HOSTS}.
+
+@item @code{max_delayed_threads}
+Don't start more than this number of threads to handle @code{INSERT DELAYED}
+statements. If you try to insert data into a new table after all @code{INSERT
+DELAYED} threads are in use, the row will be inserted as if the
+@code{DELAYED} attribute wasn't specified.
+
+@item @code{max_join_size}
+Joins that are probably going to read more than @code{max_join_size}
+records return an error. Set this value if your users tend to perform joins
+without a @code{WHERE} clause that take a long time and return
+millions of rows.
+
+@item @code{max_heap_table_size}
+Don't allow creation of heap tables bigger than this.
+
+@item @code{max_sort_length}
+The number of bytes to use when sorting @code{BLOB} or @code{TEXT}
+values (only the first @code{max_sort_length} bytes of each value
+are used; the rest are ignored).
+
+@item @code{max_tmp_tables}
+(This option doesn't yet do anything).
+Maximum number of temporary tables a client can keep open at the same time.
+
+@item @code{max_write_lock_count}
+After this many write locks, allow some read locks to run in between.
+
+@item @code{myisam_sort_buffer_size}
+The buffer that is allocated when sorting the index when doing a @code{REPAIR}
+table.
+
+@item @code{net_buffer_length}
+The communication buffer is reset to this size between queries. This
+should not normally be changed, but if you have very little memory, you
+can set it to the expected size of a query. (That is, the expected length of
+SQL statements sent by clients. If statements exceed this length, the buffer
+is automatically enlarged, up to @code{max_allowed_packet} bytes.)
+
+@item @code{net_retry_count}
+If a read on a communication port is interrupted, retry this many times
+before giving up. This value should be quite high on @code{FreeBSD} as
+internal interrupts is sent to all threads.
+
+@item @code{net_read_timeout}
+Number of seconds to wait for more data from a connection before aborting
+the read. Note that when we don't expect data from a connection, the timeout
+is defined by @code{write_timeout}.
+
+@item @code{net_write_timeout}
+Number of seconds to wait for a block to be written to a connection before
+aborting the write.
+
+@item @code{record_buffer}
+Each thread that does a sequential scan allocates a buffer of this
+size for each table it scans. If you do many sequential scans, you may
+want to increase this value.
+
+@item @code{query_buffer_size}
+The initial allocation of the query buffer. If most of your queries are
+long (like when inserting blobs), you should increase this!
+
+@item @code{skip_show_databases}
+This prevents people from doing @code{SHOW DATABASES}, if they don't
+have the @code{PROCESS_PRIV} privilege. This can improve security if
+you're concerned about people being able to see what databases and
+tables other users have.
+
+@item @code{slow_launch_time}
+If the creating of the thread longer than this (in seconds), the
+@code{Slow_launch_threads} counter will be incremented.
+
+@item @code{sort_buffer}
+Each thread that needs to do a sort allocates a buffer of this
+size. Increase this value for faster @code{ORDER BY} or @code{GROUP BY}
+operations.
+@xref{Temporary files}.
+
+@item @code{table_cache}
+The number of open tables for all threads. Increasing this value
+increases the number of file descriptors that @code{mysqld} requires.
+@strong{MySQL} needs two file descriptors for each unique open table.
+See below for comments on file descriptor limits. You can check if you
+need to increase the table cache by checking the @code{Opened_tables}
+variable. @xref{SHOW}. If this variable is big and you don't do
+@code{FLUSH TABLES} a lot (which just forces all tables to be closed and
+reopenend), then you should increase the value of this variable.
+
+For information about how the table cache works, see @ref{Table cache}.
+
+@item @code{thread_cache_size}
+How many threads we should keep keep in a cache for reuse. When a
+client disconnects the clients threads is put in the cache if there
+isn't more than @code{thread_cache_size} threads from before. All new
+threads are first taken from the cache and only when the cache is empty
+a new thread is created. This variable can be increased to improve
+performance if you have a lot of new connections (Normally this doesn't
+however give a notable performance improvement if you have a good
+thread implementation).
+
+@item @code{thread_concurrency}
+On Solaris, @code{mysqld} will call @code{thr_setconcurrency()} with
+this value. @code{thr_setconcurrency()} permits the application to give
+the threads system a hint, for the desired number of threads that should
+be run at the same time.
+
+@item @code{thread_stack}
+The stack size for each thread. Many of the limits detected by the
+@code{crash-me} test are dependent on this value. The default is
+large enough for normal operation. @xref{Benchmarks}.
+
+@item @code{tmp_table_size}
+If an in-memory temporary table exceeds this size, @strong{MySQL}
+will automatically convert it to an on-disk @code{MyISAM} table.
+Increase the value of @code{tmp_table_size} if you do many advanced
+@code{GROUP BY} queries and you have lots of memory.
+
+@item @code{wait_timeout}
+The number of seconds the server waits for activity on a connection before
+closing it. See also @code{interactive_timeout}.
+@end table
+
+The manual section that describes tuning @strong{MySQL} contains some
+information of how to tune the above variables.
+
+@findex Threads
+@findex PROCESSLIST
+@node SHOW PROCESSLIST, SHOW GRANTS, SHOW VARIABLES, SHOW
+@subsection SHOW information about connected threads (processes)
+
+@code{SHOW PROCESSLIST} shows you which threads are running. You can
+also get this information using the @code{mysqladmin processlist}
+command. If you have the @strong{process} privilege, you can see all
+threads. Otherwise, you can see only your own threads. @xref{KILL, ,
+@code{KILL}}. If you don't use the the @code{FULL} option, then only
+the first 100 characters of each query will be shown.
+
+@node SHOW GRANTS, , SHOW PROCESSLIST, SHOW
+@subsection SHOW GRANTS (privileges) for a user
+
+@code{SHOW GRANTS FOR user} lists the grant commands that must be issued to
+duplicate the grants for a user.
+
+@example
+mysql> SHOW GRANTS FOR root@@localhost;
++---------------------------------------------------------------------+
+| Grants for root@@localhost |
++---------------------------------------------------------------------+
+| GRANT ALL PRIVILEGES ON *.* TO 'root'@@'localhost' WITH GRANT OPTION |
++---------------------------------------------------------------------+
+@end example
+
+@findex EXPLAIN
+@findex SELECT, optimizing
+@node EXPLAIN, DESCRIBE, SHOW, Reference
+@section @code{EXPLAIN} syntax (Get information about a @code{SELECT})
+
+@example
+ EXPLAIN tbl_name
+or EXPLAIN SELECT select_options
+@end example
+
+@code{EXPLAIN tbl_name} is a synonym for @code{DESCRIBE tbl_name} or
+@code{SHOW COLUMNS FROM tbl_name}.
+
+When you precede a @code{SELECT} statement with the keyword @code{EXPLAIN},
+@strong{MySQL} explains how it would process the @code{SELECT}, providing
+information about how tables are joined and in which order.
+
+With the help of @code{EXPLAIN}, you can see when you must add indexes
+to tables to get a faster @code{SELECT} that uses indexes to find the
+records. You can also see if the optimizer joins the tables in an optimal
+order. To force the optimizer to use a specific join order for a
+@code{SELECT} statement, add a @code{STRAIGHT_JOIN} clause.
+
+For non-simple joins, @code{EXPLAIN} returns a row of information for each
+table used in the @code{SELECT} statement. The tables are listed in the order
+they would be read. @strong{MySQL} resolves all joins using a single-sweep
+multi-join method. This means that @strong{MySQL} reads a row from the first
+table, then finds a matching row in the second table, then in the third table
+and so on. When all tables are processed, it outputs the selected columns and
+backtracks through the table list until a table is found for which there are
+more matching rows. The next row is read from this table and the process
+continues with the next table.
+
+Output from @code{EXPLAIN} includes the following columns:
+
+@table @code
+@item table
+The table to which the row of output refers.
+
+@item type
+The join type. Information about the various types is given below.
+
+@item possible_keys
+The @code{possible_keys} column indicates which indexes @strong{MySQL}
+could use to find the rows in this table. Note that this column is
+totally independent of the order of the tables. That means that some of
+the keys in possible_keys may not be useable in practice with the
+generated table order.
+
+If this column is empty, there are no relevant indexes. In this case,
+you may be able to improve the performance of your query by examining
+the @code{WHERE} clause to see if it refers to some column or columns
+that would be suitable for indexing. If so, create an appropriate index
+and check the query with @code{EXPLAIN} again. @xref{ALTER TABLE}.
+
+To see what indexes a table has, use @code{SHOW INDEX FROM tbl_name}.
+
+@item key
+The @code{key} column indicates the key that @strong{MySQL} actually
+decided to use. The key is @code{NULL} if no index was chosen. If
+@strong{MySQL} chooses the wrong index, you can probably force
+@strong{MySQL} to use another index by using @code{myisamchk --analyze},
+@xref{myisamchk syntax}, or by using @code{USE INDEX/IGNORE INDEX}.
+@xref{JOIN}.
+
+@item key_len
+The @code{key_len} column indicates the length of the key that
+@strong{MySQL} decided to use. The length is @code{NULL} if the
+@code{key} is @code{NULL}. Note that this tell us how many parts of a
+multi-part key @strong{MySQL} will actually use.
+
+@item ref
+The @code{ref} column shows which columns or constants are used with the
+@code{key} to select rows from the table.
+
+@item rows
+The @code{rows} column indicates the number of rows @strong{MySQL}
+believes it must examine to execute the query.
+
+@item Extra
+This column contains additional information of how @strong{MySQL} will
+resolve the query. Here follows an explanation of the different text
+strings that can be found in this column:
+
+@table @code
+@item Not exists
+@strong{MySQL} was able to do a @code{LEFT JOIN} optimization on the
+query and will not examine more rows in this table for a row combination
+after it founds one rows that matches the @code{LEFT JOIN} criteria.
+@item @code{range checked for each record (index map: #)}
+@strong{MySQL} didn't find a real good index to use. It will instead for
+each row combination in the preceding tables do a check which index to
+use (if any) use this index to retrieve the rows from the table. This
+isn't very fast but is of course faster than having to do a join without
+an index.
+@item Using filesort
+@strong{MySQL} will need to do an extra pass to find out how to retrieve
+the rows in sorted order. The sort is done by going through all rows
+according to the @code{join type} and storing the sort key + pointer to
+the row for all rows that match the @code{WHERE}. Then the keys are
+sorted. Finally the rows are retrieved in sorted order.
+@item Using index
+The column information is retrieved from the table using only
+information in the index tree without having to do an additional seek to
+read the actually row. This can be done when all the used columns for
+the table are part of the same index.
+@item Using temporary
+To be able to resolve the query @strong{MySQL} will need to create a
+temporary table to hold the result. This typically happens if you do an
+@code{ORDER BY} on a different column set than you did an @code{GROUP
+BY} on.
+@item Where used
+A @code{WHERE} clause will be used to restrict which rows will be
+matched against the next table or sent to the client. If you don't have
+this information and the the table is of type @code{ALL} or @code{index}
+you may have something wrong in your query (if you don't intend to
+fetch/examine all rows from the table).
+@end table
+
+If you want to get your queries as fast as possible, you should look out for
+@code{Using filesort} and @code{Using temporary}.
+@end table
+
+The different join types are listed below, ordered from best to worst type:
+
+@cindex System table
+@cindex Table, system
+@table @code
+@item system
+The table has only one row (= system table). This is a special case of
+the @code{const} join type.
+
+@cindex Constant table
+@cindex Table, constant
+@item const
+The table has at most one matching row, which will be read at the start
+of the query. Because there is only one row, values from the column in
+this row can be regarded as constants by the rest of the
+optimizer. @code{const} tables are very fast as they are read only once!
+
+@item eq_ref
+One row will be read from this table for each combination of rows from
+the previous tables. This the best possible join type, other than the
+@code{const} types. It is used when all parts of an index are used by
+the join and the index is @code{UNIQUE} or a @code{PRIMARY KEY}.
+
+@item ref
+All rows with matching index values will be read from this table for each
+combination of rows from the previous tables. @code{ref} is used if the join
+uses only a leftmost prefix of the key, or if the key is not @code{UNIQUE}
+or a @code{PRIMARY KEY} (in other words, if the join cannot select a single
+row based on the key value). If the key that is used matches only a few rows,
+this join type is good.
+
+@item range
+Only rows that are in a given range will be retrieved, using an index to
+select the rows. The @code{ref} column indicates which index is used.
+
+@item index
+This is the same as @code{ALL}, except that only the index tree is
+scanned. This is usually faster than @code{ALL}, as the index file is usually
+smaller than the data file.
+
+@item ALL
+A full table scan will be done for each combination of rows from the
+previous tables. This is normally not good if the table is the first
+table not marked @code{const}, and usually @strong{very} bad in all other
+cases. You normally can avoid @code{ALL} by adding more indexes, so that
+the row can be retrieved based on constant values or column values from
+earlier tables.
+@end table
+
+You can get a good indication of how good a join is by multiplying all values
+in the @code{rows} column of the @code{EXPLAIN} output. This should tell you
+roughly how many rows @strong{MySQL} must examine to execute the query. This
+number is also used when you restrict queries with the @code{max_join_size}
+variable.
+@xref{Server parameters}.
+
+The following example shows how a @code{JOIN} can be optimized progressively
+using the information provided by @code{EXPLAIN}.
+
+Suppose you have the @code{SELECT} statement shown below, that you examine
+using @code{EXPLAIN}:
+
+@example
+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;
+@end example
+
+For this example, assume that:
+
+@itemize @bullet
+@item
+The columns being compared have been declared as follows:
+
+@multitable @columnfractions .1 .2 .7
+@item @strong{Table} @tab @strong{Column} @tab @strong{Column type}
+@item @code{tt} @tab @code{ActualPC} @tab @code{CHAR(10)}
+@item @code{tt} @tab @code{AssignedPC} @tab @code{CHAR(10)}
+@item @code{tt} @tab @code{ClientID} @tab @code{CHAR(10)}
+@item @code{et} @tab @code{EMPLOYID} @tab @code{CHAR(15)}
+@item @code{do} @tab @code{CUSTNMBR} @tab @code{CHAR(15)}
+@end multitable
+
+@item
+The tables have the indexes shown below:
+
+@multitable @columnfractions .1 .9
+@item @strong{Table} @tab @strong{Index}
+@item @code{tt} @tab @code{ActualPC}
+@item @code{tt} @tab @code{AssignedPC}
+@item @code{tt} @tab @code{ClientID}
+@item @code{et} @tab @code{EMPLOYID} (primary key)
+@item @code{do} @tab @code{CUSTNMBR} (primary key)
+@end multitable
+
+@item
+The @code{tt.ActualPC} values aren't evenly distributed.
+@end itemize
+
+Initially, before any optimizations have been performed, the @code{EXPLAIN}
+statement produces the following information:
+
+@example
+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)
+@end example
+
+Because @code{type} is @code{ALL} for each table, this output indicates that
+@strong{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! For the case at hand, this is @code{74 * 2135 * 74 * 3872 =
+45,268,558,720} rows. If the tables were bigger, you can only imagine how
+long it would take...
+
+One problem here is that @strong{MySQL} can't (yet) use indexes on columns
+efficiently if they are declared differently. In this context,
+@code{VARCHAR} and @code{CHAR} are the same unless they are declared as
+different lengths. Because @code{tt.ActualPC} is declared as @code{CHAR(10)}
+and @code{et.EMPLOYID} is declared as @code{CHAR(15)}, there is a length
+mismatch.
+
+To fix this disparity between column lengths, use @code{ALTER TABLE} to
+lengthen @code{ActualPC} from 10 characters to 15 characters:
+
+@example
+mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR(15);
+@end example
+
+Now @code{tt.ActualPC} and @code{et.EMPLOYID} are both @code{VARCHAR(15)}.
+Executing the @code{EXPLAIN} statement again produces this result:
+
+@example
+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
+@end example
+
+This is not perfect, but is much better (the product of the @code{rows}
+values is now less by a factor of 74). This version is executed in a couple
+of seconds.
+
+A second alteration can be made to eliminate the column length mismatches
+for the @code{tt.AssignedPC = et_1.EMPLOYID} and @code{tt.ClientID =
+do.CUSTNMBR} comparisons:
+
+@example
+mysql> ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),
+ MODIFY ClientID VARCHAR(15);
+@end example
+
+Now @code{EXPLAIN} produces the output shown below:
+
+@example
+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
+@end example
+
+This is ``almost'' as good as it can get.
+
+The remaining problem is that, by default, @strong{MySQL} assumes that values
+in the @code{tt.ActualPC} column are evenly distributed, and that isn't the
+case for the @code{tt} table. Fortunately, it is easy to tell @strong{MySQL}
+about this:
+
+@example
+shell> myisamchk --analyze PATH_TO_MYSQL_DATABASE/tt
+shell> mysqladmin refresh
+@end example
+
+Now the join is ``perfect'', and @code{EXPLAIN} produces this result:
+
+@example
+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
+@end example
+
+Note that the @code{rows} column in the output from @code{EXPLAIN} is an
+``educated guess'' from the @strong{MySQL} join optimizer; To optimize a
+query, you should check if the numbers are even close to the truth. If not,
+you may get better performance by using @code{STRAIGHT_JOIN} in your
+@code{SELECT} statement and trying to list the tables in a different order in
+the @code{FROM} clause.
+
+@findex DESC
+@findex DESCRIBE
+@node DESCRIBE, COMMIT, EXPLAIN, Reference
+@section @code{DESCRIBE} syntax (Get information about columns)
+
+@example
+@{DESCRIBE | DESC@} tbl_name @{col_name | wild@}
+@end example
+
+@code{DESCRIBE} provides information about a table's columns. @code{col_name}
+may be a column name or a string containing the SQL @samp{%} and @samp{_}
+wildcard characters.
+
+If the column types are different than you expect them to be based on a
+@code{CREATE TABLE} statement, note that @strong{MySQL} sometimes changes column
+types.
+@xref{Silent column changes}.
+
+@cindex Oracle compatibility
+@cindex Compatibility, with Oracle
+This statement is provided for Oracle compatibility.
+
+The @code{SHOW} statement provides similar information.
+@xref{SHOW, , @code{SHOW}}.
+
+
+@findex BEGIN
+@findex COMMIT
+@findex ROLLBACK
+@node COMMIT, LOCK TABLES, DESCRIBE, Reference
+@section @code{BEGIN/COMMIT/ROLLBACK} syntax
+
+By default, @strong{MySQL} runs in @code{autocommit} mode. This means that
+as soon as you execute an update, @strong{MySQL} will store the update on
+disk.
+
+If you are using @code{BDB} tables, you can put @strong{MySQL} into
+non-@code{autocommit} mode with the following command:
+
+@example
+SET AUTOCOMMIT=0
+@end example
+
+After this you must use @code{COMMIT} to store your changes to disk or
+@code{ROLLBACK} if you want to ignore the changes you have made since
+the beginning of your transaction.
+
+If you want to switch from @code{AUTOCOMMIT} mode for one serie of
+statements, you can use the @code{BEGIN} or @code{BEGIN WORK} statement.
+
+@example
+BEGIN;
+SELECT @@A:=SUM(salary) FROM table1 WHERE type=1;
+UPDATE table2 SET summmary=@@A WHERE type=1;
+COMMIT;
+@end example
+
+Note that if you are using non-transaction-safe tables, the changes will be
+stored at once, independent of the status of the @code{autocommit} mode.
+
+@findex LOCK TABLES
+@findex UNLOCK TABLES
+@node LOCK TABLES, SET OPTION, COMMIT, Reference
+@section @code{LOCK TABLES/UNLOCK TABLES} syntax
+
+@example
+LOCK TABLES tbl_name [AS alias] @{READ | [READ LOCAL] | [LOW_PRIORITY] WRITE@}
+ [, tbl_name @{READ | [LOW_PRIORITY] WRITE@} ...]
+...
+UNLOCK TABLES
+@end example
+
+@code{LOCK TABLES} locks tables for the current thread. @code{UNLOCK TABLES}
+releases any locks held by the current thread. All tables that are locked by
+the current thread are automatically unlocked when the thread issues another
+@code{LOCK TABLES}, or when the connection to the server is closed.
+
+If a thread obtains a @code{READ} lock on a table, that thread (and all other
+threads) can only read from the table. If a thread obtains a @code{WRITE}
+lock on a table, then only the thread holding the lock can @code{READ} from
+or @code{WRITE} to the table. Other threads are blocked.
+
+The difference between @code{READ LOCAL} and @code{READ} is that
+@code{READ LOCAL} allows non-conflicting @code{INSERT} statements to
+execute while the lock is held. This can't however be used if you are
+going to manipulate the database files outside @strong{MySQL} while you
+hold the lock.
+
+Each thread waits (without timing out) until it obtains all the locks it has
+requested.
+
+@code{WRITE} locks normally have higher priority than @code{READ} locks, to
+ensure that updates are processed as soon as possible. This means that if one
+thread obtains a @code{READ} lock and then another thread requests a
+@code{WRITE} lock, subsequent @code{READ} lock requests will wait until the
+@code{WRITE} thread has gotten the lock and released it. You can use
+@code{LOW_PRIORITY WRITE} locks to allow other threads to obtain @code{READ}
+locks while the thread is waiting for the @code{WRITE} lock. You should only
+use @code{LOW_PRIORITY WRITE} locks if you are sure that there will
+eventually be a time when no threads will have a @code{READ} lock.
+
+When you use @code{LOCK TABLES}, you must lock all tables that you are
+going to use and you must use the same alias that you are going to use in
+your queries! If you are using a table multiple times in a query (with
+aliases), you must get a lock for each alias! This policy ensures that
+table locking is deadlock free.
+
+Note that you should @strong{NOT} lock any tables that you are using with
+@code{INSERT DELAYED}. This is because that in this case the @code{INSERT}
+is done by a separate thread.
+
+Normally, you don't have to lock tables, as all single @code{UPDATE} statements
+are atomic; no other thread can interfere with any other currently executing
+SQL statement. There are a few cases when you would like to lock tables
+anyway:
+
+@itemize @bullet
+@item
+If you are going to run many operations on a bunch of tables, it's much
+faster to lock the tables you are going to use. The downside is, of course,
+that no other thread can update a @code{READ}-locked table and no other
+thread can read a @code{WRITE}-locked table.
+@item
+@strong{MySQL} doesn't support a transaction environment, so you must use
+@code{LOCK TABES} if you want to ensure that no other thread comes between a
+@code{SELECT} and an @code{UPDATE}. The example shown below
+requires @code{LOCK TABLES} in order to execute safely:
+
+@example
+mysql> LOCK TABLES trans READ, customer WRITE;
+mysql> select sum(value) from trans where customer_id= some_id;
+mysql> update customer set total_value=sum_from_previous_statement
+ where customer_id=some_id;
+mysql> UNLOCK TABLES;
+@end example
+
+Without @code{LOCK TABLES}, there is a chance that another thread might
+insert a new row in the @code{trans} table between execution of the
+@code{SELECT} and @code{UPDATE} statements.
+@end itemize
+
+By using incremental updates (@code{UPDATE customer SET
+value=value+new_value}) or the @code{LAST_INSERT_ID()} function, you can
+avoid using @code{LOCK TABLES} in many cases.
+
+You can also solve some cases by using the user-level lock functions
+@code{GET_LOCK()} and @code{RELEASE_LOCK()}. These locks are saved in a hash
+table in the server and implemented with @code{pthread_mutex_lock()} and
+@code{pthread_mutex_unlock()} for high speed.
+@xref{Miscellaneous functions}.
+
+See @ref{Internal locking}, for more information on locking policy.
+
+You can also lock all tables in all databases with read locks with the
+@code{FLUSH TABLES WITH READ LOCK} command. @xref{FLUSH}.
+
+@findex SET OPTION
+@node SET OPTION, GRANT, LOCK TABLES, Reference
+@section @code{SET} syntax
+
+@example
+SET [OPTION] SQL_VALUE_OPTION= value, ...
+@end example
+
+@code{SET OPTION} sets various options that affect the operation of the
+server or your client. Any option you set remains in effect until the
+current session ends, or until you set the option to a different value.
+
+@table @code
+@item CHARACTER SET character_set_name | DEFAULT
+This maps all strings from and to the client with the given mapping.
+Currently the only option for @code{character_set_name} is
+@code{cp1251_koi8}, but you can easily add new mappings by editing the
+@file{sql/convert.cc} file in the @strong{MySQL} source distribution. The
+default mapping can be restored by using a @code{character_set_name} value of
+@code{DEFAULT}.
+
+Note that the syntax for setting the @code{CHARACTER SET} option differs
+from the syntax for setting the other options.
+
+@item PASSWORD = PASSWORD('some password')
+@cindex Passwords, setting
+Set the password for the current user. Any non-anonymous user can change his
+own password!
+
+@item PASSWORD FOR user = PASSWORD('some password')
+@cindex Passwords, setting
+Set the password for a specific user on the current server host. Only a user
+with access to the @code{mysql} database can do this. The user should be
+given in @code{user@@hostname} format, where @code{user} and @code{hostname}
+are exactly as they are listed in the @code{User} and @code{Host} columns of
+the @code{mysql.user} table entry. For example, if you had an entry with
+@code{User} and @code{Host} fields of @code{'bob'} and @code{'%.loc.gov'},
+you would write:
+
+@example
+mysql> SET PASSWORD FOR bob@@"%.loc.gov" = PASSWORD("newpass");
+
+or
+
+mysql> UPDATE mysql.user SET password=PASSWORD("newpass") where user="bob' and host="%.loc.gov";
+@end example
+
+@item SQL_AUTO_IS_NULL = 0 | 1
+If set to @code{1} (default) then one can find the last inserted row
+for a table with an auto_increment row with the following construct:
+@code{WHERE auto_increment_column IS NULL}. This is used by some
+ODBC programs like Access.
+
+@item SET AUTOCOMMIT= 0 | 1
+If set to @code{1} all changes to a table will be done at once. To start
+an multi command transaction you have to use the @code{BEGIN}
+statement. @xref{COMMIT}. If set to @code{0} you have to use @code{COMMIT} /
+@code{ROLLBACK} to accept/revoke that transaction. @xref{COMMIT}. Note
+that when you change from not @code{AUTOCOMMIT} mode to
+@code{AUTOCOMMIT} mode, @strong{MySQL} will do an automatic
+@code{COMMIT} on any open transactions.
+
+@item SQL_BIG_TABLES = 0 | 1
+@cindex The table is full
+If set to @code{1}, all temporary tables are stored on disk rather than in
+memory. This will be a little slower, but you will not get the error
+@code{The table tbl_name is full} for big @code{SELECT} operations that
+require a large temporary table. The default value for a new connection is
+@code{0} (i.e., use in-memory temporary tables).
+
+@item SQL_BIG_SELECTS = 0 | 1
+If set to @code{0}, @strong{MySQL} will abort if a @code{SELECT} is attempted
+that probably will take a very long time. This is useful when an inadvisable
+@code{WHERE} statement has been issued. A big query is defined as a
+@code{SELECT} that probably will have to examine more than
+@code{max_join_size} rows. The default value for a new connection is
+@code{1} (which will allow all @code{SELECT} statements).
+
+@item SQL_BUFFER_RESULT = 0 | 1
+@code{SQL_BUFFER_RESULT} will force the result from @code{SELECT}'s
+to be put into a temporary table. This will help @strong{MySQL} free the
+table locks early and will help in cases where it takes a long time to
+send the result set to the client.
+
+@item SQL_LOW_PRIORITY_UPDATES = 0 | 1
+If set to @code{1}, all @code{INSERT}, @code{UPDATE}, @code{DELETE} and
+and @code{LOCK TABLE WRITE} statements wait until there is no pending
+@code{SELECT} or @code{LOCK TABLE READ} on the affected table.
+
+@item SQL_MAX_JOIN_SIZE = value | DEFAULT
+Don't allow @code{SELECT}'s that will probably need to examine more than
+@code{value} row combinations. By setting this value, you can catch
+@code{SELECT}'s where keys are not used properly and that would probably
+take a long time. Setting this to a value other than @code{DEFAULT} will reset
+the @code{SQL_BIG_SELECTS} flag. If you set the @code{SQL_BIG_SELECTS}
+flag again, the @code{SQL_MAX_JOIN_SIZE} variable will be ignored.
+You can set a default value for this variable by starting @code{mysqld} with
+@code{-O max_join_size=#}.
+
+@item SQL_SAFE_MODE = 0 | 1
+If set to @code{1}, @strong{MySQL} will abort if a @code{UPDATE} or
+@code{DELETE} is attempted that doesn't use a key or @code{LIMIT} in the
+@code{WHERE} clause. This makes it possible to catch wrong updates
+when creating SQL commands by hand.
+
+@item SQL_SELECT_LIMIT = value | DEFAULT
+The maximum number of records to return from @code{SELECT} statements. If
+a @code{SELECT} has a @code{LIMIT} clause, the @code{LIMIT} takes precedence
+over the value of @code{SQL_SELECT_LIMIT}. The default value for a new
+connection is ``unlimited''. If you have changed the limit, the default value
+can be restored by using a @code{SQL_SELECT_LIMIT} value of @code{DEFAULT}.
+
+@item SQL_LOG_OFF = 0 | 1
+If set to @code{1}, no logging will be done to the standard log for this
+client, if the client has the @strong{process} privilege. This does not
+affect the update log!
+
+@item SQL_LOG_UPDATE = 0 | 1
+If set to @code{0}, no logging will be done to the update log for the client,
+if the client has the @strong{process} privilege. This does not affect the
+standard log!
+
+@item TIMESTAMP = timestamp_value | DEFAULT
+Set the time for this client. This is used to get the original timestamp if
+you use the update log to restore rows.
+
+@item LAST_INSERT_ID = #
+Set the value to be returned from @code{LAST_INSERT_ID()}. This is stored in
+the update log when you use @code{LAST_INSERT_ID()} in a command that updates
+a table.
+
+@item INSERT_ID = #
+Set the value to be used by the following @code{INSERT} command when inserting
+an @code{AUTO_INCREMENT} value. This is mainly used with the update log.
+@end table
+
+@findex GRANT
+@findex REVOKE
+@node GRANT, CREATE INDEX, SET OPTION, Reference
+@section @code{GRANT} and @code{REVOKE} syntax
+
+@example
+GRANT priv_type [(column_list)] [, priv_type [(column_list)] ...]
+ ON @{tbl_name | * | *.* | db_name.*@}
+ TO user_name [IDENTIFIED BY 'password']
+ [, user_name [IDENTIFIED BY 'password'] ...]
+ [WITH GRANT OPTION]
+
+REVOKE priv_type [(column_list)] [, priv_type [(column_list)] ...]
+ ON @{tbl_name | * | *.* | db_name.*@}
+ FROM user_name [, user_name ...]
+@end example
+
+@code{GRANT} is implemented in @strong{MySQL} 3.22.11 or later. For
+earlier @strong{MySQL} versions, the @code{GRANT} statement does nothing.
+
+The @code{GRANT} and @code{REVOKE} commands allow system administrators to
+grant and revoke rights to @strong{MySQL} users at four privilege levels:
+
+@table @strong
+@item Global level
+Global privileges apply to all databases on a given server. These privileges
+are stored in the @code{mysql.user} table.
+
+@item Database level
+Database privileges apply to all tables in a given database. These privileges
+are stored in the @code{mysql.db} and @code{mysql.host} tables.
+
+@item Table level
+Table privileges apply to all columns in a given table. These privileges are
+stored in the @code{mysql.tables_priv} table.
+
+@item Column level
+Column privileges apply to single columns in a given table. These privileges are
+stored in the @code{mysql.columns_priv} table.
+@end table
+
+For examples of how @code{GRANT} works, see @ref{Adding users}.
+
+For the @code{GRANT} and @code{REVOKE} statements, @code{priv_type} may be
+specified as any of the following:
+
+@example
+ALL PRIVILEGES FILE RELOAD
+ALTER INDEX SELECT
+CREATE INSERT SHUTDOWN
+DELETE PROCESS UPDATE
+DROP REFERENCES USAGE
+@end example
+
+@code{ALL} is a synonym for @code{ALL PRIVILEGES}. @code{REFERENCES} is not
+yet implemented. @code{USAGE} is currently a synonym for ``no privileges''.
+It can be used when you want to create a user that has no privileges.
+
+To revoke the @strong{grant} privilege from a user, use a @code{priv_type}
+value of @code{GRANT OPTION}:
+
+@example
+REVOKE GRANT OPTION ON ... FROM ...;
+@end example
+
+The only @code{priv_type} values you can specify for a table are @code{SELECT},
+@code{INSERT}, @code{UPDATE}, @code{DELETE}, @code{CREATE}, @code{DROP},
+@code{GRANT}, @code{INDEX} and @code{ALTER}.
+
+The only @code{priv_type} values you can specify for a column (that is, when
+you use a @code{column_list} clause) are @code{SELECT}, @code{INSERT} and
+@code{UPDATE}.
+
+You can set global privileges by using @code{ON *.*} syntax. You can set
+database privileges by using @code{ON db_name.*} syntax. If you specify
+@code{ON *} and you have a current database, you will set the privileges for
+that database. (@strong{Warning:} If you specify @code{ON *} and you
+@emph{don't} have a current database, you will affect the global privileges!)
+
+In order to accommodate granting rights to users from arbitrary hosts,
+@strong{MySQL} supports specifying the @code{user_name} value in the form
+@code{user@@host}. If you want to specify a @code{user} string
+containing special characters (such as @samp{-}), or a @code{host} string
+containing special characters or wildcard characters (such as @samp{%}), you
+can quote the user or host name (e.g., @code{'test-user'@@'test-hostname'}).
+
+You can specify wildcards in the hostname. For example,
+@code{user@@"%.loc.gov"} applies to @code{user} for any host in the
+@code{loc.gov} domain, and @code{user@@"144.155.166.%"} applies to @code{user}
+for any host in the @code{144.155.166} class C subnet.
+
+The simple form @code{user} is a synonym for @code{user@@"%"}.
+@strong{Note:} If you allow anonymous users to connect to the @strong{MySQL}
+server (which is the default), you should also add all local users as
+@code{user@@localhost} because otherwise the anonymous user entry for the
+local host in the @code{mysql.user} table will be used when the user tries to
+log into the @strong{MySQL} server from the local machine! Anonymous users
+are defined by inserting entries with @code{User=''} into the
+@code{mysql.user} table. You can verify if this applies to you by executing
+this query:
+
+@example
+mysql> SELECT Host,User FROM mysql.user WHERE User='';
+@end example
+
+For the moment, @code{GRANT} only supports host, table, database and
+column names up to 60 characters long. A user name can be up to 16
+characters.
+
+The privileges for a table or column are formed from the
+logical OR of the privileges at each of the four privilege
+levels. For example, if the @code{mysql.user} table specifies that a
+user has a global @strong{select} privilege, this can't be denied by an
+entry at the database, table or column level.
+
+The privileges for a column can be calculated as follows:
+
+@example
+global privileges
+OR (database privileges AND host privileges)
+OR table privileges
+OR column privileges
+@end example
+
+In most cases, you grant rights to a user at only one of the privilege
+levels, so life isn't normally as complicated as above. :) The details of the
+privilege-checking procedure are presented in
+@ref{Privilege system}.
+
+If you grant privileges for a user/hostname combination that does not exist
+in the @code{mysql.user} table, an entry is added and remains there until
+deleted with a @code{DELETE} command. In other words, @code{GRANT} may
+create @code{user} table entries, but @code{REVOKE} will not remove them;
+you must do that explicitly using @code{DELETE}.
+
+@cindex Passwords, setting
+In @strong{MySQL} 3.22.12 or later,
+if a new user is created or if you have global grant privileges, the user's
+password will be set to the password specified by the @code{IDENTIFIED BY}
+clause, if one is given. If the user already had a password, it is replaced
+by the new one.
+
+@strong{Warning:} If you create a new user but do not specify an
+@code{IDENTIFIED BY} clause, the user has no password. This is insecure.
+
+Passwords can also be set with the @code{SET PASSWORD} command.
+@xref{SET OPTION, , @code{SET OPTION}}.
+
+If you grant privileges for a database, an entry in the @code{mysql.db}
+table is created if needed. When all privileges for the database have been
+removed with @code{REVOKE}, this entry is deleted.
+
+If a user doesn't have any privileges on a table, the table is not displayed
+when the user requests a list of tables (e.g., with a @code{SHOW TABLES}
+statement).
+
+The @code{WITH GRANT OPTION} clause gives the user the ability to give
+to other users any privileges the user has at the specified privilege level.
+You should be careful to whom you give the @strong{grant} privilege, as two
+users with different privileges may be able to join privileges!
+
+You cannot grant another user a privilege you don't have yourself;
+the @strong{grant} privilege allows you to give away only those privileges
+you possess.
+
+Be aware that when you grant a user the @strong{grant} privilege at a
+particular privilege level, any privileges the user already possesses (or
+is given in the future!) at that level are also grantable by that user.
+Suppose you grant a user the @strong{insert} privilege on a database. If
+you then grant the @strong{select} privilege on the database and specify
+@code{WITH GRANT OPTION}, the user can give away not only the @strong{select}
+privilege, but also @strong{insert}. If you then grant the @strong{update}
+privilege to the user on the database, the user can give away the
+@strong{insert}, @strong{select} and @strong{update}.
+
+You should not grant @strong{alter} privileges to a normal user. If you
+do that, the user can try to subvert the privilege system by renaming
+tables!
+
+Note that if you are using table or column privileges for even one user, the
+server examines table and column privileges for all users and this will slow
+down @strong{MySQL} a bit.
+
+When @code{mysqld} starts, all privileges are read into memory.
+Database, table and column privileges take effect at once and
+user-level privileges take effect the next time the user connects.
+Modifications to the grant tables that you perform using @code{GRANT} or
+@code{REVOKE} are noticed by the server immediately.
+If you modify the grant tables manually (using @code{INSERT}, @code{UPDATE},
+etc.), you should execute a @code{FLUSH PRIVILEGES} statement or run
+@code{mysqladmin flush-privileges} to tell the server to reload the grant
+tables.
+@xref{Privilege changes}.
+
+@cindex ANSI SQL, differences from
+The biggest differences between the ANSI SQL and @strong{MySQL} versions of
+@code{GRANT} are:
+
+@itemize @bullet
+@item
+ANSI SQL doesn't have global or database-level privileges and ANSI SQL
+doesn't support all privilege types that @strong{MySQL} supports.
+
+@item
+When you drop a table in ANSI SQL, all privileges for the table are revoked.
+If you revoke a privilege in ANSI SQL, all privileges that were granted based
+on this privilege are also revoked. In @strong{MySQL}, privileges can be
+dropped only with explicit @code{REVOKE} commands or by manipulating the
+@strong{MySQL} grant tables.
+@end itemize
+
+@cindex Indexes
+@cindex Indexes, multi-part
+@cindex Multi-part index
+@findex CREATE INDEX
+@node CREATE INDEX, DROP INDEX, GRANT, Reference
+@section @code{CREATE INDEX} syntax
+
+@example
+CREATE [UNIQUE] INDEX index_name ON tbl_name (col_name[(length)],... )
+@end example
+
+The @code{CREATE INDEX} statement doesn't do anything in @strong{MySQL} prior
+to version 3.22. In 3.22 or later, @code{CREATE INDEX} is mapped to an
+@code{ALTER TABLE} statement to create indexes.
+@xref{ALTER TABLE, , @code{ALTER TABLE}}.
+
+Normally, you create all indexes on a table at the time the table itself
+is created with @code{CREATE TABLE}.
+@xref{CREATE TABLE, , @code{CREATE TABLE}}.
+@code{CREATE INDEX} allows you to add indexes to existing tables.
+
+A column list of the form @code{(col1,col2,...)} creates a multiple-column
+index. Index values are formed by concatenating the values of the given
+columns.
+
+For @code{CHAR} and @code{VARCHAR} columns, indexes can be created that
+use only part of a column, using @code{col_name(length)} syntax. (On
+@code{BLOB} and @code{TEXT} columns the length is required). The
+statement shown below creates an index using the first 10 characters of
+the @code{name} column:
+
+@example
+mysql> CREATE INDEX part_of_name ON customer (name(10));
+@end example
+
+Because most names usually differ in the first 10 characters, this index should
+not be much slower than an index created from the entire @code{name} column.
+Also, using partial columns for indexes can make the index file much smaller,
+which could save a lot of disk space and might also speed up @code{INSERT}
+operations!
+
+Note that you can only add an index on a column that can have @code{NULL}
+values or on a @code{BLOB}/@code{TEXT} column if you are useing
+@strong{MySQL} version 3.23.2 or newer and are using the @code{MyISAM}
+table type.
+
+For more information about how @strong{MySQL} uses indexes, see
+@ref{MySQL indexes, , @strong{MySQL} indexes}.
+
+@findex DROP INDEX
+@node DROP INDEX, Comments, CREATE INDEX, Reference
+@section @code{DROP INDEX} syntax
+
+@example
+DROP INDEX index_name ON tbl_name
+@end example
+
+@code{DROP INDEX} drops the index named @code{index_name} from the table
+@code{tbl_name}. @code{DROP INDEX} doesn't do anything in @strong{MySQL}
+prior to version 3.22. In 3.22 or later, @code{DROP INDEX} is mapped to an
+@code{ALTER TABLE} statement to drop the index.
+@xref{ALTER TABLE, , @code{ALTER TABLE}}.
+
+@findex Comment syntax
+@node Comments, CREATE FUNCTION, DROP INDEX, Reference
+@section Comment syntax
+
+The @strong{MySQL} server supports the @code{# to end of line}, @code{--
+to end of line} and @code{/* in-line or multiple-line */} comment
+styles:
+
+@example
+mysql> select 1+1; # This comment continues to the end of line
+mysql> select 1+1; -- This comment continues to the end of line
+mysql> select 1 /* this is an in-line comment */ + 1;
+mysql> select 1+
+/*
+this is a
+multiple-line comment
+*/
+1;
+@end example
+
+Note that the @code{--} comment style requires you to have at least one space
+after the @code{--}!
+
+Although the server understands the comment syntax just described,
+there are some limitations on the way that the @code{mysql} client
+parses @code{/* ... */} comments:
+
+@itemize @bullet
+@item
+Single-quote and double-quote characters are taken to indicate the beginning
+of a quoted string, even within a comment. If the quote is not matched by a
+second quote within the comment, the parser doesn't realize the comment has
+ended. If you are running @code{mysql} interactively, you can tell that it
+has gotten confused like this because the prompt changes from @code{mysql>}
+to @code{'>} or @code{">}.
+
+@item
+A semicolon is taken to indicate the end of the current SQL statement
+and anything following it to indicate the beginning of the next statement.
+@end itemize
+
+These limitations apply both when you run @code{mysql} interactively
+and when you put commands in a file and tell @code{mysql} to read its
+input from that file with @code{mysql < some-file}.
+
+@strong{MySQL} doesn't support the @samp{--} ANSI SQL comment style.
+@xref{Missing comments}.
+
+@findex CREATE FUNCTION
+@findex DROP FUNCTION
+@findex UDF functions
+@findex User-defined functions
+@findex Functions, user-defined
+@node CREATE FUNCTION, Reserved words, Comments, Reference
+@section @code{CREATE FUNCTION/DROP FUNCTION} syntax
+
+@example
+CREATE [AGGREGATE] FUNCTION function_name RETURNS @{STRING|REAL|INTEGER@}
+ SONAME shared_library_name
+
+DROP FUNCTION function_name
+@end example
+
+A user-definable function (UDF) is a way to extend @strong{MySQL} with a new
+function that works like native (built in) @strong{MySQL} functions such as
+@code{ABS()} and @code{CONCAT()}.
+
+@code{AGGREGATE} is a new option for @strong{MySQL} 3.23. An
+@code{AGGREGATE} function works exactly like a native @strong{MySQL}
+@code{GROUP} function like @code{SUM} or @code{COUNT()}.
+
+@code{CREATE FUNCTION} saves the function's name, type and shared library
+name in the @code{mysql.func} system table. You must have the
+@strong{insert} and @strong{delete} privileges for the @code{mysql} database
+to create and drop functions.
+
+All active functions are reloaded each time the server starts, unless
+you start @code{mysqld} with the @code{--skip-grant-tables} option. In
+this case, UDF initialization is skipped and UDFs are unavailable.
+(An active function is one that has been loaded with @code{CREATE FUNCTION}
+and not removed with @code{DROP FUNCTION}.)
+
+For instructions on writing user-definable functions, see @ref{Adding
+functions}. For the UDF mechanism to work, functions must be written in C or
+C++, your operating system must support dynamic loading and you must have
+compiled @code{mysqld} dynamically (not statically).
+
+@cindex Keywords
+@cindex Reserved words
+@cindex Reserved words, exceptions
+@node Reserved words, , CREATE FUNCTION, Reference
+@section Is MySQL picky about reserved words?
+
+A common problem stems from trying to create a table with column names that
+use the names of datatypes or functions built into @strong{MySQL}, such as
+@code{TIMESTAMP} or @code{GROUP}. You're allowed to do it (for example,
+@code{ABS} is an allowed column name), but whitespace is not allowed between
+a function name and the @samp{(} when using functions whose names are also
+column names.
+
+The following words are explicitly reserved in @strong{MySQL}. Most of
+them are forbidden by ANSI SQL92 as column and/or table names
+(for example, @code{group}).
+A few are reserved because @strong{MySQL} needs them and is
+(currently) using a @code{yacc} parser:
+
+@c This is fixed by including the symbols table from lex.h here and then running
+@c fix-mysql-reserved-words in emacs (or let David do it):
+@c (defun fix-mysql-reserved-words ()
+@c (interactive)
+@c (let ((cnt 0))
+@c (insert "\n@item ")
+@c (while (looking-at "[ \t]*{ +\"\\([^\"]+\\)\"[ \t]*,.*\n")
+@c (replace-match "@code{\\1}")
+@c (incf cnt)
+@c (if (> cnt 3)
+@c (progn
+@c (setf cnt 0)
+@c (insert "\n@item "))
+@c (insert " @tab ")))))
+@c But remove the non alphanumeric entries by hand first.
+@c Updated after 3.23.4 990928 by David
+
+@multitable @columnfractions .25 .25 .25 .25
+@item @code{action} @tab @code{add} @tab @code{aggregate} @tab @code{all}
+@item @code{alter} @tab @code{after} @tab @code{and} @tab @code{as}
+@item @code{asc} @tab @code{avg} @tab @code{avg_row_length} @tab @code{auto_increment}
+@item @code{between} @tab @code{bigint} @tab @code{bit} @tab @code{binary}
+@item @code{blob} @tab @code{bool} @tab @code{both} @tab @code{by}
+@item @code{cascade} @tab @code{case} @tab @code{char} @tab @code{character}
+@item @code{change} @tab @code{check} @tab @code{checksum} @tab @code{column}
+@item @code{columns} @tab @code{comment} @tab @code{constraint} @tab @code{create}
+@item @code{cross} @tab @code{current_date} @tab @code{current_time} @tab @code{current_timestamp}
+@item @code{data} @tab @code{database} @tab @code{databases} @tab @code{date}
+@item @code{datetime} @tab @code{day} @tab @code{day_hour} @tab @code{day_minute}
+@item @code{day_second} @tab @code{dayofmonth} @tab @code{dayofweek} @tab @code{dayofyear}
+@item @code{dec} @tab @code{decimal} @tab @code{default} @tab @code{delayed}
+@item @code{delay_key_write} @tab @code{delete} @tab @code{desc} @tab @code{describe}
+@item @code{distinct} @tab @code{distinctrow} @tab @code{double} @tab @code{drop}
+@item @code{end} @tab @code{else} @tab @code{escape} @tab @code{escaped}
+@item @code{enclosed} @tab @code{enum} @tab @code{explain} @tab @code{exists}
+@item @code{fields} @tab @code{file} @tab @code{first} @tab @code{float}
+@item @code{float4} @tab @code{float8} @tab @code{flush} @tab @code{foreign}
+@item @code{from} @tab @code{for} @tab @code{full} @tab @code{function}
+@item @code{global} @tab @code{grant} @tab @code{grants} @tab @code{group}
+@item @code{having} @tab @code{heap} @tab @code{high_priority} @tab @code{hour}
+@item @code{hour_minute} @tab @code{hour_second} @tab @code{hosts} @tab @code{identified}
+@item @code{ignore} @tab @code{in} @tab @code{index} @tab @code{infile}
+@item @code{inner} @tab @code{insert} @tab @code{insert_id} @tab @code{int}
+@item @code{integer} @tab @code{interval} @tab @code{int1} @tab @code{int2}
+@item @code{int3} @tab @code{int4} @tab @code{int8} @tab @code{into}
+@item @code{if} @tab @code{is} @tab @code{isam} @tab @code{join}
+@item @code{key} @tab @code{keys} @tab @code{kill} @tab @code{last_insert_id}
+@item @code{leading} @tab @code{left} @tab @code{length} @tab @code{like}
+@item @code{lines} @tab @code{limit} @tab @code{load} @tab @code{local}
+@item @code{lock} @tab @code{logs} @tab @code{long} @tab @code{longblob}
+@item @code{longtext} @tab @code{low_priority} @tab @code{max} @tab @code{max_rows}
+@item @code{match} @tab @code{mediumblob} @tab @code{mediumtext} @tab @code{mediumint}
+@item @code{middleint} @tab @code{min_rows} @tab @code{minute} @tab @code{minute_second}
+@item @code{modify} @tab @code{month} @tab @code{monthname} @tab @code{myisam}
+@item @code{natural} @tab @code{numeric} @tab @code{no} @tab @code{not}
+@item @code{null} @tab @code{on} @tab @code{optimize} @tab @code{option}
+@item @code{optionally} @tab @code{or} @tab @code{order} @tab @code{outer}
+@item @code{outfile} @tab @code{pack_keys} @tab @code{partial} @tab @code{password}
+@item @code{precision} @tab @code{primary} @tab @code{procedure} @tab @code{process}
+@item @code{processlist} @tab @code{privileges} @tab @code{read} @tab @code{real}
+@item @code{references} @tab @code{reload} @tab @code{regexp} @tab @code{rename}
+@item @code{replace} @tab @code{restrict} @tab @code{returns} @tab @code{revoke}
+@item @code{rlike} @tab @code{row} @tab @code{rows} @tab @code{second}
+@item @code{select} @tab @code{set} @tab @code{show} @tab @code{shutdown}
+@item @code{smallint} @tab @code{soname} @tab @code{sql_big_tables} @tab @code{sql_big_selects}
+@item @code{sql_low_priority_updates} @tab @code{sql_log_off} @tab @code{sql_log_update} @tab @code{sql_select_limit}
+@item @code{sql_small_result} @tab @code{sql_big_result} @tab @code{sql_warnings} @tab @code{straight_join}
+@item @code{starting} @tab @code{status} @tab @code{string} @tab @code{table}
+@item @code{tables} @tab @code{temporary} @tab @code{terminated} @tab @code{text}
+@item @code{then} @tab @code{time} @tab @code{timestamp} @tab @code{tinyblob}
+@item @code{tinytext} @tab @code{tinyint} @tab @code{trailing} @tab @code{to}
+@item @code{type} @tab @code{use} @tab @code{using} @tab @code{unique}
+@item @code{unlock} @tab @code{unsigned} @tab @code{update} @tab @code{usage}
+@item @code{values} @tab @code{varchar} @tab @code{variables} @tab @code{varying}
+@item @code{varbinary} @tab @code{with} @tab @code{write} @tab @code{when}
+@item @code{where} @tab @code{year} @tab @code{year_month} @tab @code{zerofill}
+@end multitable
+
+The following symbols (from the table above) are disallowed by ANSI SQL
+but allowed by @strong{MySQL} as column/table names. This is because some
+of these names are very natural names and a lot of people have already
+used them.
+
+@itemize @bullet
+@item @code{ACTION}
+@item @code{BIT}
+@item @code{DATE}
+@item @code{ENUM}
+@item @code{NO}
+@item @code{TEXT}
+@item @code{TIME}
+@item @code{TIMESTAMP}
+@end itemize
+
+@cindex Table types, Choosing
+@cindex BDB table type
+@cindex Berkeley_db table type
+@cindex ISAM table type
+@cindex HEAP table type
+@cindex MySQL table types
+@cindex MyISAM table type
+@node Table types, Tutorial, Reference, Top
+@chapter MySQL table types
+
+As of @strong{MySQL} 3.23.6, you can choose between three basic
+table formats. When you create a new table, you can tell @strong{MySQL}
+which table type it should use for the table. @strong{MySQL} will
+always create a @code{.frm} file to hold the table and column
+definitions. Depending on the table type the index and data will be
+stored in other files.
+
+The default table type in @strong{MySQL} is @code{MyISAM}. If you are
+trying to use a table type that is not incompiled or activated,
+@strong{MySQL} will instead create a table of type @code{MyISAM}.
+
+You can convert tables between different types with the @code{ALTER
+TABLE} statement. @xref{ALTER TABLE, , @code{ALTER TABLE}}.
+
+Note that @strong{MySQL} supports two different kind of
+tables. Transactions safe tables (@code{BDB}) and not transaction safe
+tables (@code{ISAM},@code{MyISAM} and @code{HEAP}.
+
+Advantages of transaction safe tables (TST)
+
+@itemize @bullet
+@item
+Safer; Even if @code{MySQL} crashes or you get hardware problems, you
+can get your data back; Either by automatic recovery or from a backup
++ the transaction log.
+@item
+You can combine many statements and accept these all in one go with
+the @code{COMMIT} command.
+@item
+You can execute @code{ROLLBACK} to ignore your changes (if you are not
+running in auto commit mode).
+@item
+If an update fails, all your changes will be restored. (With NTST tables all
+changes that has taken place are permanent)
+@end itemize
+
+Advantages of not transaction safe tables (NTST):
+
+@itemize @bullet
+@item
+Much faster as there is no transcation overhead.
+@item
+Will use less disk space as there is no overhead of transactions.
+@item
+Will use less memory to do updates.
+@end itemize
+
+You can combine TST and NTST tables in the same statements to get the best
+of both worlds.
+
+@menu
+* MyISAM:: MyISAM tables
+* ISAM:: ISAM tables
+* HEAP:: HEAP tables
+* BDB:: BDB or Berkeley_db tables
+@end menu
+
+@node MyISAM, ISAM, Table types, Table types
+@section MyISAM tables
+
+@code{MyISAM} is the default table type in @strong{MySQL} 3.23. It's
+based on the @code{ISAM} code and has a lot of useful extensions.
+
+The index is stored in a file with the @code{.MYI} (MYIndex) extension
+and the data is stored in file with the @code{.MYD} (MYData) extension.
+You can check/repair @code{MyISAM} tables with the @code{myisamchk}
+utility. @xref{Crash recovery}.
+
+The following is new in @code{MyISAM}:
+
+@itemize @bullet
+@item
+You can @code{INSERT} new rows in a table without deleted rows,
+while other threads are reading from the table.
+@item
+Support for big files (63-bit) on filesystems/operating systems that
+support big files.
+@item
+All data is stored with the low byte first. This makes the data machine and
+OS independent. The only requirement is that the machine uses two's-complement
+signed integers (as every machine for the last 20 years has)
+and IEEE floating point format (also totally dominant among mainstream
+machines). The only area of machines that may not support binary
+compatibility are embedded systems (because they sometimes have peculiar
+processors).
+@item
+All number keys are stored with high byte first to give better index
+compression.
+@item
+Internal handling of one @code{AUTO_INCREMENT} column. @code{MyISAM}
+will automatically update this on @code{INSERT/UPDATE}. The
+@code{AUTO_INCREMENT} value can be reset with @code{myisamchk}. This
+will make @code{AUTO_INCREMENT} columns faster (at least 10 %) and old
+numbers will not be reused as with the old ISAM. Note that when a
+@code{AUTO_INCREMENT} is defined on the end of a multi-part-key the old
+behavior is still present.
+@item
+When inserted in sorted order (as when you are using an @code{AUTO_INCREMENT}
+column) the key tree will be split so that the high node only contains one
+key. This will improve the space utilization in the key tree.
+@item
+@code{BLOB} and @code{TEXT} columns can be indexed.
+@item
+@code{NULL} values are allowed in indexed columns. This takes 0-1
+bytes/key.
+@item
+Maximum key length is now 500 bytes by default. In cases of keys longer
+than 250 bytes, a bigger key block size than the default of 1024 bytes
+is used for this key.
+@item
+Maximum number of keys/table enlarged to 32 as default. This can be
+enlarged to 64 without having to recompile @code{myisamchk}.
+@item
+There is a flag in the @code{MyISAM} file that indicates whether or not the
+table was closed correctly. This will soon be used for automatic repair
+in the @strong{MySQL} server.
+@item
+@code{myisamchk} will mark tables as checked if one runs it with
+@code{--update-state}. @code{myisamchk --fast} will only check those
+tables that don't have this mark.
+@item
+@code{myisamchk -a} stores statistics for key parts (and not only for
+whole keys as in @code{ISAM}).
+@item
+Dynamic size rows will now be much less fragmented when mixing deletes
+with updates and inserts. This is done by automatically combining adjacent
+deleted blocks and by extending blocks if the next block is deleted.
+@item
+@code{myisampack} can pack @code{BLOB} and @code{VARCHAR} columns.
+@end itemize
+
+@code{MyISAM} also supports the following things, which @strong{MySQL}
+will be able to use in the near future.
+
+@itemize @bullet
+@item
+Support for a true @code{VARCHAR} type; A @code{VARCHAR} column starts
+with a length stored in 2 bytes.
+@item
+Tables with @code{VARCHAR} may have fixed or dynamic record length.
+@item
+@code{VARCHAR} and @code{CHAR} may be up to 64K.
+All key segments have their own language definition. This will enable
+@strong{MySQL} to have different language definitions per column.
+@item
+A hashed computed index can be used for @code{UNIQUE}; This will allow
+you to have @code{UNIQUE} on any combination of columns in a table. (You
+can't search on a @code{UNIQUE} computed index, however.)
+@end itemize
+
+Note that index files are usually much smaller with @code{MyISAM} than with
+@code{ISAM}. This means that @code{MyISAM} will normally use less
+system resources than @code{ISAM}, but will need more CPU when inserting
+data into compressed index.
+
+@menu
+* Key space:: Space needed for keys
+* MyISAM table formats:: MyISAM table formats
+@end menu
+
+@node Key space, MyISAM table formats, MyISAM, MyISAM
+@subsection Space needed for keys
+
+@strong{MySQL} can support different index types, but the normal type is
+ISAM or MyISAM. These use a B-tree index and you can roughly calculate
+the size for the index file as @code{(key_length+4)/0.67}, summed over
+all keys. (This is for the worst case when all keys are inserted in
+sorted order and we don't have any compressed keys.)
+
+String indexes are space compressed. If the first index part is a
+string, it will also be prefix compressed. Space compression makes the
+index file smaller than the above figures if the string column has a lot
+of trailing space or is a @code{VARCHAR} column that is not always used
+to the full length. Prefix compression is used on keys that start
+with a string. Prefix compression helps if there are many strings
+with an identical prefix.
+
+In @code{MyISAM} tables, you can also prefix compress numbers by specifying
+@code{PACK_KEYS=1} when you create the table. This helps when you have
+many integer keys which have an identical prefix when the numbers are stored
+high-byte first.
+
+@node MyISAM table formats, , Key space, MyISAM
+@subsection MyISAM table formats
+
+@strong{MyISAM} supports 3 different table types. 2 of them are chosen
+automatically depending on the type of columns you are using. The third,
+compressed tables, can only be created with the @code{myisampack} tool.
+
+@menu
+* Static format:: Static (Fixed-length) table characteristics
+* Dynamic format:: Dynamic table characteristics
+* Compressed format:: Compressed table characteristics
+@end menu
+
+@node Static format, Dynamic format, MyISAM table formats, MyISAM table formats
+@subsubsection Static (Fixed-length) table characteristics
+
+This is the default format. It's used when the table contains no
+@code{VARCHAR}, @code{BLOB} or @code{TEXT} columns.
+
+This format is the simplest and most secure format. It is also the
+fastest of the on-disk formats. The speed comes from the easy way data
+can be found on disk. When looking up something with an index and static
+format it is very simple, just multiply the row number by the row length.
+
+Also when scanning a table it is very easy to read a constant number of
+records with each disk read.
+
+The security comes from if your computer crashes when writing to a
+fixed size MyISAM file, @code{myisamchk} can easily figure out where each
+row starts and ends. So it can usually reclaim all records except the
+partially written one. Note that in @strong{MySQL} all indexes can always be
+reconstructed.
+
+@itemize @bullet
+@item
+All @code{CHAR}, @code{NUMERIC} and @code{DECIMAL} columns are space-padded
+to the column width.
+@item
+Very quick.
+@item
+Easy to cache.
+@item
+Easy to reconstruct after a crash, because records are located in fixed
+positions.
+@item
+Doesn't have to be reorganized (with @code{myisamchk}) unless a huge number of
+records are deleted and you want to return free disk space to the operating
+system.
+@item
+Usually requires more disk space than dynamic tables.
+@end itemize
+
+@node Dynamic format, Compressed format, Static format, MyISAM table formats
+@subsubsection Dynamic table characteristics
+
+This format is used if the table contains any @code{VARCHAR}, @code{BLOB}
+or @code{TEXT} columns or if the table was created with
+@code{ROW_FORMAT=dynamic}.
+
+This format is a litte more complex because each row has to have a header
+that says how long it is. One record can also end up at more than one
+location when it is made longer at an update.
+
+You can use @code{OPTIMIZE table} or @code{myisamchk} to defragment a
+table. If you have static data that you access/change a lot in the same
+table as some @code{VARCHAR} or @code{BLOB} columns, it might be a good
+idea to move the dynamic columns to other tables just to avoid
+fragmentation.
+
+@itemize @bullet
+@item
+All string columns are dynamic (except those with a length less than 4).
+@item
+Each record is preceded by a bitmap indicating which columns are empty
+(@code{''}) for string columns, or zero for numeric columns (this isn't
+the same as columns containing @code{NULL} values). If a string column
+has a length of zero after removal of trailing spaces, or a numeric
+column has a value of zero, it is marked in the bit map and not saved to
+disk. Non-empty strings are saved as a length byte plus the string
+contents.
+@item
+Usually takes much less disk space than fixed-length tables.
+@item
+Each record uses only as much space as is required. If a record becomes
+larger, it is split into as many pieces as required. This results in record
+fragmentation.
+@item
+If you update a row with information that extends the row length, the
+row will be fragmented. In this case, you may have to run @code{myisamchk
+-r} from time to time to get better performance. Use @code{myisamchk -ei
+tbl_name} for some statistics.
+@item
+Not as easy to reconstruct after a crash, because a record may be fragmented
+into many pieces and a link (fragment) may be missing.
+@item
+The expected row length for dynamic sized records is:
+
+@example
+3
++ (number of columns + 7) / 8
++ (number of char columns)
++ packed size of numeric columns
++ length of strings
++ (number of NULL columns + 7) / 8
+@end example
+
+There is a penalty of 6 bytes for each link. A dynamic record is linked
+whenever an update causes an 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 @code{myisamchk -ed}. All links may be removed with @code{myisamchk -r}.
+@end itemize
+
+@node Compressed format, , Dynamic format, MyISAM table formats
+@subsubsection Compressed table characteristics
+
+This is a read only type that is generated with the optional
+@code{myisampack} tool (@code{pack_isam} for @code{ISAM} tables).
+
+@itemize @bullet
+@item
+All MySQL distributions, even those that existed before @strong{MySQL}
+went GPL, can read tables that were compressed with @code{myisampack}.
+@item
+Compressed tables takes very little disk space. This minimizes disk usage which
+is very nice when using slow disks (like CD-ROMs).
+@item
+Each record is compressed separately (very little access overhead). The
+header for a record is fixed (1-3 bytes) depending on the biggest record in the
+table. Each column is compressed differently. Some of the compression types
+are:
+@itemize @minus
+@item
+There is usually a different Huffman table for each column.
+@item
+Suffix space compression.
+@item
+Prefix space compression.
+@item
+Numbers with value @code{0} are stored using 1 bit.
+@item
+If values in an integer column have a small range, the column is stored using
+the smallest possible type. For example, a @code{BIGINT} column (8 bytes) may
+be stored as a @code{TINYINT} column (1 byte) if all values are in the range
+@code{0} to @code{255}.
+@item
+If a column has only a small set of possible values, the column type is
+converted to @code{ENUM}.
+@item
+A column may use a combination of the above compressions.
+@end itemize
+@item
+Can handle fixed or dynamic length records, but not @code{BLOB} or @code{TEXT}
+columns.
+@item
+Can be uncompressed with @code{myisamchk}.
+@end itemize
+
+@node ISAM, HEAP, MyISAM, Table types
+@section ISAM tables
+
+You can also use the deprecated ISAM table type. This will disappear
+rather soon because @code{MyISAM} is a better implementation of the same
+thing. ISAM uses a @code{B-tree} index. The index is stored in a file
+with the @code{.ISM} extension and the data is stored in file with the
+@code{.ISD} extension. You can check/repair ISAM tables with the
+@code{isamchk} utility. @xref{Crash recovery}.
+
+@code{ISAM} has the following features/properties:
+
+@itemize @bullet
+@item Compressed and fixed length keys
+@item Fixed and dynamic record length
+@item 16 keys with 16 key parts / key
+@item Max key length 256 (default)
+@item Data is stored in machine format; this is fast, but is machine/OS dependent.
+@end itemize
+
+Most of the things for @code{MyISAM} tables are also true for @code{ISAM}
+tables. @xref{MyISAM}. The major differences compared to @code{MyISAM}
+tables are:
+
+@itemize @bullet
+@item ISAM tables are not binary portable across OS/Platforms.
+@item Can't handle tables > 4G.
+@item Only support prefix compression on strings
+@item Smaller key limits.
+@item Dynamic tables gets more fragmented.
+@item Tables are compressed with @code{pack_isam} rather than with @code{myisampack}.
+@end itemize
+
+@node HEAP, BDB, ISAM, Table types
+@section HEAP tables
+
+@code{HEAP} tables use a hashed index and are stored in memory. This
+makes them very fast, but if @strong{MySQL} crashes you will lose all
+data stored in them. @code{HEAP} is very useful for temporary tables!
+
+The @strong{MySQL} internal HEAP tables uses 100% dynamic hashing
+without overflow areas. There is no extra space needed for free lists.
+@code{HEAP} tables also don't have problems with delete + inserts, which
+normally is common with hashed tables..
+
+@example
+mysql> CREATE TABLE test TYPE=HEAP SELECT ip,SUM(downloads) as down
+ FROM log_table GROUP BY ip;
+mysql> SELECT COUNT(ip),AVG(down) FROM test;
+mysql> DROP TABLE test;
+@end example
+
+Here are some things you should consider when you use @code{HEAP} tables:
+
+@itemize @bullet
+@item
+You should always use specify @code{MAX_ROWS} in the @code{CREATE} statement
+to ensure that you accidently do not use all memory.
+@item
+Indexes will only be used with @code{=} and @code{<=>} (but are VERY fast).
+@item
+@code{HEAP} tables can only use whole keys to search for a row; compare this
+to @code{MyISAM} tables where any prefix of the key can be used to find rows.
+@item
+@code{HEAP} tables use a fixed record length format.
+@item
+@code{HEAP} doesn't support @code{BLOB}/@code{TEXT} columns.
+@item
+@code{HEAP} doesn't support @code{AUTO_INCREMENT} columns.
+@item
+@code{HEAP} doesn't support an index on a @code{NULL} column.
+@item
+You can have non-unique keys in a @code{HEAP} table (this isn't common for
+hashed tables).
+@item
+@code{HEAP} tables are shared between all clients (just like any other
+table).
+@item
+You can't search for the next entry in order (that is to use the index
+to do a @code{ORDER BY}).
+@item
+Data for @code{HEAP} tables are allocated in small blocks. The tables
+are 100% dynamic (on inserting). No overflow areas and no extra key
+space is needed. Deleted rows are put in a linked list and are
+reused when you insert new data into the table.
+@item
+You need enough extra memory for all HEAP tables that you want to use at
+the same time.
+@item
+To free memory, you should execute @code{DELETE FROM heap_table} or
+@code{DROP TABLE heap_table}.
+@item
+@strong{MySQL} cannot find out how approximately many rows there
+are between two values (this is used by the range optimizer to decide which
+index to use). This may affect some queries if you change a @code{MyISAM}
+table to a @code{HEAP} table.
+@item
+To ensure that you accidentally don't do anything stupid, you can't create
+@code{HEAP} tables bigger than @code{max_heap_table_size}.
+@end itemize
+
+Memory needed for one row in a @code{HEAP} table is:
+
+SUM_OVER_ALL_KEYS(max_length_of_key + sizeof(char*)*2) +
+ALIGN(length_of_row+1,sizeof(char*))
+
+@code{sizeof(char*)} is 4 on 32 bit machines and 8 on 64 bit machines.
+
+@node BDB, , HEAP, Table types
+@section BDB or Berkeley_db tables
+
+Berkeley DB (@uref{http://www.sleepycat.com}) has provided
+@strong{MySQL} with a transaction safe table handler. This will survive
+crashes and also provides @code{COMMIT} and @code{ROLLBACK} on
+transactions. In order to build MySQL 3.23.x (BDB support first appeared
+in 3.23.15) with support for @code{BDB} tables, you will need Berkeley
+DB 3.1.14 or newer which can be downloaded from
+@uref{http://www.mysql.com/downloads/mysql-3.23.html}; or also from
+Sleepycat's download page at
+@uref{http://www.sleepycat.com/download.html}.
+
+To install Berkeley DB first uncompress the @code{BDB} distribution
+and follow the instructions in the README provided in the distiribution
+directory. Basicly what you need to do is:
+@itemize @bullet
+@item
+cd build_[your_os]
+@item
+../dist/configure
+@item
+make
+@item
+make install
+@end itemize
+
+Please refer to the manual provided by @code{BDB} distribution for
+more/updated information.
+
+After this you need to configure your @strong{MySQL} with
+--with-berkeley-db=DIR The directory is the one where you installed
+@code{BDB} binaries with make install. (Usually it is
+/usr/local/BerkeleyDB.3.1/) You can give additional options to
+@strong{MySQL} configure, --with-berkeley-db-includes=DIR and
+--with-berkeley-db-libs=DIR, if the @code{BDB} includes and/or libs
+directory is not under the first directory. By default they are.
+Then complete the @strong{MySQL} installation as normal.
+
+Even if Berkeley DB is in itself very tested and reliably, the
+@strong{MySQL} interface is still very alpha, but we are actively
+improving and optimizing it to get it this stable real soon.
+
+If you are running with @code{AUTOCOMMIT=0} then your changes in @code{BDB}
+tables will not be updated until you execute @code{COMMIT}. Instead of commit
+you can execute @code{ROLLBACK} to forget your changes. @xref{COMMIT}.
+
+The following options to @code{mysqld} can be used to change the behavour of
+BDB tables:
+
+@multitable @columnfractions .30 .70
+@item --bdb-home= directory @tab Berkeley home direcory
+@item --bdb-lock-detect=# @tab Berkeley lock detect. One of (DEFAULT, OLDEST, RANDOM or YOUNGEST)
+@item --bdb-logdir=directory @tab Berkeley DB log file directory
+@item --bdb-nosync @tab Don't synchronously flush logs
+@item --bdb-recover @tab Start Berkeley DB in recover mode
+@item --bdb-tmpdir=directory @tab Berkeley DB tempfile name
+@item --skip-bdb @tab Don't use berkeley db.
+@end multitable
+
+If you use @code{--skip-bdb}, @strong{MySQL} will not initialize the
+Berkeley DB library and this will save a lot of memory. You can of course
+not use @code{BDB} tables if you are using this option.
+
+Normally you should start mysqld with @code{--bdb-recover} if you intend
+to use BDB tables. This may however give you problems when you try to
+start mysqld if the BDB log files are corrupted. @xref{Starting server}.
+
+Some characteristic of @code{BDB} tables:
+
+@itemize @bullet
+@item
+All @code{BDB} tables must have a primary key.
+@item
+If all columns you access in a @code{BDB} tables is part of the same index or
+part of the the primary key then @strong{MySQL} can execute the query
+without having to access the actual row. In a @code{MyISAM} table the
+above holds only if the columns are part of the same index.
+@item
+@code{LOCK TABLES} works on @code{BDB} tables as with other tables. If
+you don't use @code{LOCK TABLE}, @strong{MYSQL} will issue an internal
+multiple write lock on the table to ensure that the table will be
+properly locked if one another thread issues a table lock.
+@item
+@code{ALTER TABLE} doesn't yet work on @code{BDB} tables.
+@item
+Internal locking in @code{BDB} tables are done on page level.
+@item
+Scanning is slower than with @code{MyISAM} tables as one has data in BDB
+tables is stored in B-trees and not in a separate data file.
+@item
+One must in the application always be prepared to handle the case that
+any change of a @code{BDB} table may make an automatic rollback and any
+read may fail with a deadlock error.
+@item
+Keys are not compressed to previous keys as with ISAM or MyISAM
+tables. In other words, the key information will take a little more
+space in @code{BDB} tables compared to MyISAM tables with don't use
+@code{PACK_KEYS=0}.
+@item
+One must do a @code{FLUSH LOGS} from time to time to sync to get checkpoints
+for the @code{BDB} tables.
+@item
+As transaction logs take more place than ordinary logs it's more important
+to rotate and remove old logs when using @code{BDB} tables than using other table
+types.
+@end itemize
+
+Some things that we have to fix in the near future:
+
+@itemize @bullet
+@item
+Remove the requirement that @code{BDB} tables must have a primary key. This
+will be fixed by having an automatic hidden auto_increment column for
+the tables without a primary key.
+@item
+@code{LOCK TABLES} should work as for other @strong{MySQL} tables.
+@item
+@code{ALTER TABLE} doesn't yet work.
+@item
+@code{SHOW TABLE STATUS} doesn't yet provide that much information for BDB
+tables.
+@end itemize
+
+@node Tutorial, Server, Table types, Top
+@chapter MySQL Tutorial
+
+@menu
+* Connecting-disconnecting:: Connecting to and disconnecting from the server
+* Entering queries:: Entering queries
+* Examples:: Examples
+* Searching on two keys:: Searching on two keys
+* Database use:: Creating and using a database
+* Getting information:: Getting information about databases and tables
+* Batch mode:: Using @code{mysql} in batch mode
+* Twin:: Queries from twin project
+@end menu
+
+This chapter provides a tutorial introduction to @strong{MySQL} by showing
+how to use the @code{mysql} client program to create and use a simple
+database. @code{mysql} (sometimes referred to as the ``terminal monitor'' or
+just ``monitor'') is an interactive program that allows you to connect to a
+@strong{MySQL} server, run queries and view the results. @code{mysql} may
+also be used in batch mode: you place your queries in a file beforehand, then
+tell @code{mysql} to execute the contents of the file. Both ways of using
+@code{mysql} are covered here.
+
+To see a list of options provided by @code{mysql}, invoke it with
+the @code{--help} option:
+
+@example
+shell> mysql --help
+@end example
+
+This chapter assumes that @code{mysql} is installed on your machine, and that
+a @strong{MySQL} server is available to which you can connect. If this is
+not true, contact your @strong{MySQL} administrator. (If @emph{you} are the
+administrator, you will need to consult other sections of this manual.)
+
+The chapter describes the entire process of setting up and using a
+database. If you are interested only in accessing an already-existing
+database, you may want to skip over the sections that describe how to
+create the database and the tables it contains.
+
+Because this chapter is tutorial in nature, many details are necessarily left
+out. Consult the relevant sections of the manual for more
+information on the topics covered here.
+
+@node Connecting-disconnecting, Entering queries, Tutorial, Tutorial
+@section Connecting to and disconnecting from the server
+
+To connect to the server, you'll usually need to provide a @strong{MySQL}
+user name when you invoke @code{mysql} and, most likely, a password. If the
+server runs on a machine other than the one where you log in, you'll also
+need to specify a hostname. Contact your administrator to find out what
+connection parameters you should use to connect (i.e., what host, user name
+and password to use). Once you know the proper parameters, you should be
+able to connect like this:
+
+@example
+shell> mysql -h host -u user -p
+Enter password: ********
+@end example
+
+The @code{********} represents your password; enter it when @code{mysql}
+displays the @code{Enter password:} prompt.
+
+If that works, you should see some introductory information followed by a
+@code{mysql>} prompt:
+
+
+@example
+shell> mysql -h host -u user -p
+Enter password: ********
+Welcome to the MySQL monitor. Commands end with ; or \g.
+Your MySQL connection id is 459 to server version: 3.22.20a-log
+
+Type 'help' for help.
+
+mysql>
+@end example
+
+The prompt tells you that @code{mysql} is ready for you to enter commands.
+
+Some @strong{MySQL} installations allow users to connect as the ``anonymous''
+(unnamed) user to the server running on the local host. If this is the case
+on your machine, you should be able to connect to that server by invoking
+@code{mysql} without any options:
+
+@example
+shell> mysql
+@end example
+
+After you have connected successfully, you can disconnect any time by typing
+@code{QUIT} at the @code{mysql>} prompt:
+
+@example
+mysql> QUIT
+Bye
+@end example
+
+You can also disconnect by typing control-D.
+
+Most examples in the following sections assume you are connected to the
+server. They indicate this by the @code{mysql>} prompt.
+
+@node Entering queries, Examples, Connecting-disconnecting, Tutorial
+@section Entering queries
+
+Make sure you are connected to the server, as discussed in the previous
+section. Doing so will not in itself select any database to work with, but
+that's okay. At this point, it's more important to find out a little about
+how to issue queries than to jump right in creating tables, loading data
+into them and retrieving data from them. This section describes the basic
+principles of entering commands, using several queries you can try out to
+familiarize yourself with how @code{mysql} works.
+
+Here's a simple command that asks the server to tell you its version number
+and the current date. Type it in as shown below following the @code{mysql>}
+prompt and hit the RETURN key:
+
+@example
+mysql> SELECT VERSION(), CURRENT_DATE;
++--------------+--------------+
+| version() | CURRENT_DATE |
++--------------+--------------+
+| 3.22.20a-log | 1999-03-19 |
++--------------+--------------+
+1 row in set (0.01 sec)
+mysql>
+@end example
+
+This query illustrates several things about @code{mysql}:
+
+@itemize @bullet
+@item
+A command normally consists of a SQL statement followed by a semicolon.
+(There are some exceptions where a semicolon is not needed. @code{QUIT},
+mentioned earlier, is one of them. We'll get to others later.)
+
+@item
+When you issue a command, @code{mysql} sends it to the server for execution
+and displays the results, then prints another @code{mysql>} to indicate
+that it is ready for another command.
+
+@item
+@code{mysql} displays query output as a table (rows and columns). The first
+row contains labels for the columns. The rows following are the query
+results. Normally, column labels are the names of the columns you fetch from
+database tables. If you're retrieving the value of an expression rather than
+a table column (as in the example just shown), @code{mysql} labels the column
+using the expression itself.
+
+@item
+@code{mysql} shows how many rows were returned, and how long the query took
+to execute, which gives you a rough idea of server performance. These values
+are imprecise because they represent wall clock time (not CPU or machine
+time), and because they are affected by factors such as server load and
+network latency. (For brevity, the ``rows in set'' line is not shown in
+the remaining examples in this chapter.)
+@end itemize
+
+Keywords may be entered in any lettercase. The following queries are
+equivalent:
+
+@example
+mysql> SELECT VERSION(), CURRENT_DATE;
+mysql> select version(), current_date;
+mysql> SeLeCt vErSiOn(), current_DATE;
+@end example
+
+Here's another query. It demonstrates that you can use @code{mysql} as a
+simple calculator:
+
+@example
+mysql> SELECT SIN(PI()/4), (4+1)*5;
++-------------+---------+
+| SIN(PI()/4) | (4+1)*5 |
++-------------+---------+
+| 0.707107 | 25 |
++-------------+---------+
+@end example
+
+The commands shown thus far have been relatively short, single-line
+statements. You can even enter multiple statements on a single line.
+Just end each one with a semicolon:
+
+@example
+mysql> SELECT VERSION(); SELECT NOW();
++--------------+
+| version() |
++--------------+
+| 3.22.20a-log |
++--------------+
+
++---------------------+
+| NOW() |
++---------------------+
+| 1999-03-19 00:15:33 |
++---------------------+
+@end example
+
+A command need not be given all on a single line, so lengthy commands that
+require several lines are not a problem. @code{mysql} determines where your
+statement ends by looking for the terminating semicolon, not by looking for
+the end of the input line. (In other words, @code{mysql}
+accepts free-format input: it collects input lines but does not execute them
+until it sees the semicolon.)
+
+Here's a simple multiple-line statement:
+
+@example
+mysql> SELECT
+ -> USER()
+ -> ,
+ -> CURRENT_DATE;
++--------------------+--------------+
+| USER() | CURRENT_DATE |
++--------------------+--------------+
+| joesmith@@localhost | 1999-03-18 |
++--------------------+--------------+
+@end example
+
+In this example, notice how the prompt changes from @code{mysql>} to
+@code{->} after you enter the first line of a multiple-line query. This is
+how @code{mysql} indicates that it hasn't seen a complete statement and is
+waiting for the rest. The prompt is your friend, because it provides
+valuable feedback. If you use that feedback, you will always be aware of
+what @code{mysql} is waiting for.
+
+If you decide you don't want to execute a command that you are in the
+process of entering, cancel it by typing @code{\c}:
+
+@example
+mysql> SELECT
+ -> USER()
+ -> \c
+mysql>
+@end example
+
+Here, too, notice the prompt. It switches back to @code{mysql>} after you
+type @code{\c}, providing feedback to indicate that @code{mysql} is ready
+for a new command.
+
+The following table shows each of the prompts you may see and summarizes what
+they mean about the state that @code{mysql} is in:
+
+@multitable @columnfractions .10 .9
+@item @strong{Prompt} @tab @strong{Meaning}
+@item @code{mysql>} @tab Ready for new command
+@item @code{@ @ @ @ ->} @tab Waiting for next line of multiple-line command
+@item @code{@ @ @ @ '>} @tab Waiting for next line, collecting a string that begins
+with a single quote (@samp{'})
+@item @code{@ @ @ @ ">} @tab Waiting for next line, collecting a string that begins
+with a double quote (@samp{"})
+@end multitable
+
+Multiple-line statements commonly occur ``by accident'' when you intend to
+issue a command on a single line, but forget the terminating semicolon. In
+this case, @code{mysql} waits for more input:
+
+@example
+mysql> SELECT USER()
+ ->
+@end example
+
+If this happens to you (you think you've entered a statement but the only
+response is a @code{->} prompt), most likely @code{mysql} is waiting for the
+semicolon. If you don't notice what the prompt is telling you, you might sit
+there for a while before realizing what you need to do. Enter a semicolon to
+complete the statement, and @code{mysql} will execute it:
+
+@example
+mysql> SELECT USER()
+ -> ;
++--------------------+
+| USER() |
++--------------------+
+| joesmith@@localhost |
++--------------------+
+@end example
+
+The @code{'>} and @code{">} prompts occur during string collection.
+In @strong{MySQL}, you can write strings surrounded by either @samp{'}
+or @samp{"} characters (for example, @code{'hello'} or @code{"goodbye"}),
+and @code{mysql} lets you enter strings that span multiple lines. When you
+see a @code{'>} or @code{">} prompt, it means that you've entered a line
+containing a string that begins with a @samp{'} or @samp{"} quote character,
+but have not yet entered the matching quote that terminates the string.
+That's fine if you really are entering a multiple-line string, but how likely
+is that? Not very. More often, the @code{'>} and @code{">} prompts indicate
+that you've inadvertantly left out a quote character. For example:
+
+@example
+mysql> SELECT * FROM my_table WHERE name = "Smith AND age < 30;
+ ">
+@end example
+
+If you enter this @code{SELECT} statement, then hit RETURN and wait for the
+result, nothing will happen. Instead of wondering, ``why does this
+query take so long?,'' notice the clue provided by the @code{">} prompt. It
+tells you that @code{mysql} expects to see the rest of an unterminated
+string. (Do you see the error in the statement? The string @code{"Smith} is
+missing the second quote.)
+
+At this point, what do you do? The simplest thing is to cancel the command.
+However, you cannot just type @code{\c} in this case, because @code{mysql}
+interprets it as part of the string that it is collecting! Instead, enter
+the closing quote character (so @code{mysql} knows you've finished the
+string), then type @code{\c}:
+
+@example
+mysql> SELECT * FROM my_table WHERE name = "Smith AND age < 30;
+ "> "\c
+mysql>
+@end example
+
+The prompt changes back to @code{mysql>}, indicating that @code{mysql}
+is ready for a new command.
+
+It's important to know what the @code{'>} and @code{">} prompts signify,
+because if you mistakenly enter an unterminated string, any further lines you
+type will appear to be ignored by @code{mysql} --- including a line
+containing @code{QUIT}! This can be quite confusing, especially if you
+don't know that you need to supply the terminating quote before you can
+cancel the current command.
+
+@node Examples, Searching on two keys, Entering queries, Tutorial
+@section Examples of common queries
+
+Here follows examples of how to solve some common problems with
+@strong{MySQL}.
+
+Some of the examples use the table @code{shop} to hold the price of each
+article (item number) for certain traders (dealers). Supposing that each
+trader has a single fixed price per article, then (@code{item},
+@code{trader}) is a primary key for the records.
+
+You can create the example table as:
+
+@example
+CREATE TABLE shop (
+ article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
+ dealer CHAR(20) DEFAULT '' NOT NULL,
+ price DOUBLE(16,2) DEFAULT '0.00' NOT NULL,
+ PRIMARY KEY(article, dealer));
+
+INSERT INTO shop VALUES
+(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),(3,'C',1.69),
+(3,'D',1.25),(4,'D',19.95);
+@end example
+
+Okay, so the example data is:
+
+@example
+SELECT * FROM shop
+
++---------+--------+-------+
+| article | dealer | price |
++---------+--------+-------+
+| 0001 | A | 3.45 |
+| 0001 | B | 3.99 |
+| 0002 | A | 10.99 |
+| 0003 | B | 1.45 |
+| 0003 | C | 1.69 |
+| 0003 | D | 1.25 |
+| 0004 | D | 19.95 |
++---------+--------+-------+
+@end example
+
+@menu
+* example-Maximum-column:: The maximum value for a column
+* example-Maximum-row:: The row holding the maximum of a certain column
+* example-Maximum-column-group:: Maximum of column: per group: only the values
+* example-Maximum-column-group-row:: The rows holding the group-wise maximum of a certain field
+* example-Foreign keys:: Using foreign keys
+@end menu
+
+@node example-Maximum-column, example-Maximum-row, Examples, Examples
+@subsection The maximum value for a column
+
+``What's the highest item number?''
+
+@example
+SELECT MAX(article) AS article FROM shop
+
++---------+
+| article |
++---------+
+| 4 |
++---------+
+@end example
+
+@node example-Maximum-row, example-Maximum-column-group, example-Maximum-column, Examples
+@subsection The row holding the maximum of a certain column
+
+``Find number, dealer, and price of the most expensive article.''
+
+In ANSI SQL this is easily done with a sub-query:
+
+@example
+SELECT article, dealer, price
+FROM shop
+WHERE price=(SELECT MAX(price) FROM shop)
+@end example
+
+In @strong{MySQL} (which does not yet have sub-selects), just do it in
+two steps:
+
+@enumerate
+@item
+Get the maximum price value from the table with a @code{SELECT} statement.
+@item
+Using this value compile the actual query:
+@example
+SELECT article, dealer, price
+FROM shop
+WHERE price=19.95
+@end example
+@end enumerate
+
+Another solution is to sort all rows descending by price and only
+get the first row using the @strong{MySQL} specific @code{LIMIT} clause:
+
+@example
+SELECT article, dealer, price
+FROM shop
+ORDER BY price DESC
+LIMIT 1
+@end example
+
+@strong{Note}: If there are several most expensive articles (e.g. each 19.95)
+the @code{LIMIT} solution shows only one of them!
+
+@node example-Maximum-column-group, example-Maximum-column-group-row, example-Maximum-row, Examples
+@subsection Maximum of column: per group: only the values
+
+``What's the highest price per article?''
+
+@example
+SELECT article, MAX(price) AS price
+FROM shop
+GROUP BY article
+
++---------+-------+
+| article | price |
++---------+-------+
+| 0001 | 3.99 |
+| 0002 | 10.99 |
+| 0003 | 1.69 |
+| 0004 | 19.95 |
++---------+-------+
+@end example
+
+@node example-Maximum-column-group-row, example-Foreign keys, example-Maximum-column-group, Examples
+@subsection The rows holding the group-wise maximum of a certain field
+
+``For each article, find the dealer(s) with the most expensive price.''
+
+In ANSI SQL, I'd do it with a sub-query like this:
+
+@example
+SELECT article, dealer, price
+FROM shop s1
+WHERE price=(SELECT MAX(s2.price)
+ FROM shop s2
+ WHERE s1.article = s2.article)
+@end example
+
+In @strong{MySQL} it's best do it in several steps:
+
+@enumerate
+@item
+Get the list of (article,maxprice). @xref{example-Maximum-column-group-row}.
+@item
+For each article get the corresponding rows which have the stored maximum
+price.
+@end enumerate
+
+This can easily be done with a temporary table:
+
+@example
+CREATE TEMPORARY TABLE tmp (
+ article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
+ price DOUBLE(16,2) DEFAULT '0.00' NOT NULL);
+
+LOCK TABLES article read;
+
+INSERT INTO tmp SELECT article, MAX(price) FROM shop GROUP BY article;
+
+SELECT article, dealer, price FROM shop, tmp
+WHERE shop.article=tmp.article AND shop.price=tmp.price;
+
+UNLOCK TABLES;
+
+DROP TABLE tmp;
+@end example
+
+If you don't use a @code{TEMPORARY} table, you must also lock the 'tmp' table.
+
+``Can it be done with a single query?''
+
+Yes, but only by using a quite inefficient trick that I call the
+``MAX-CONCAT trick'':
+
+@example
+SELECT article,
+ SUBSTRING( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 7) AS dealer,
+ 0.00+LEFT( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 6) AS price
+FROM shop
+GROUP BY article;
+
++---------+--------+-------+
+| article | dealer | price |
++---------+--------+-------+
+| 0001 | B | 3.99 |
+| 0002 | A | 10.99 |
+| 0003 | C | 1.69 |
+| 0004 | D | 19.95 |
++---------+--------+-------+
+@end example
+
+The last example can of course be made a bit more efficient by doing the
+splitting of the concatenated column in the client.
+
+@node example-Foreign keys, , example-Maximum-column-group-row, Examples
+@subsection Using foreign keys
+
+You don't need foreign keys to join 2 tables.
+
+The only thing @strong{MySQL} doesn't do is @code{CHECK} to make sure that
+the keys you use really exist in the table(s) you're referencing and it
+doesn't automatically delete rows from table with a foreign key
+definition. If you use your keys like normal, it'll work just fine!
+
+
+@example
+CREATE TABLE persons (
+ id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
+ name CHAR(60) NOT NULL,
+ PRIMARY KEY (id)
+);
+
+CREATE TABLE shirts (
+ id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
+ style ENUM('t-shirt', 'polo', 'dress') NOT NULL,
+ color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL,
+ owner SMALLINT UNSIGNED NOT NULL REFERENCES persons,
+ PRIMARY KEY (id)
+);
+
+
+INSERT INTO persons VALUES (NULL, 'Antonio Paz');
+
+INSERT INTO shirts VALUES
+(NULL, 'polo', 'blue', LAST_INSERT_ID()),
+(NULL, 'dress', 'white', LAST_INSERT_ID()),
+(NULL, 't-shirt', 'blue', LAST_INSERT_ID());
+
+
+INSERT INTO persons VALUES (NULL, 'Lilliana Angelovska');
+
+INSERT INTO shirts VALUES
+(NULL, 'dress', 'orange', LAST_INSERT_ID()),
+(NULL, 'polo', 'red', LAST_INSERT_ID()),
+(NULL, 'dress', 'blue', LAST_INSERT_ID()),
+(NULL, 't-shirt', 'white', LAST_INSERT_ID());
+
+
+SELECT * FROM persons;
++----+---------------------+
+| id | name |
++----+---------------------+
+| 1 | Antonio Paz |
+| 2 | Lilliana Angelovska |
++----+---------------------+
+
+SELECT * FROM shirts;
++----+---------+--------+-------+
+| id | style | color | owner |
++----+---------+--------+-------+
+| 1 | polo | blue | 1 |
+| 2 | dress | white | 1 |
+| 3 | t-shirt | blue | 1 |
+| 4 | dress | orange | 2 |
+| 5 | polo | red | 2 |
+| 6 | dress | blue | 2 |
+| 7 | t-shirt | white | 2 |
++----+---------+--------+-------+
+
+
+SELECT s.* FROM persons p, shirts s
+ WHERE p.name LIKE 'Lilliana%'
+ AND s.owner = p.id
+ AND s.color <> 'white';
+
++----+-------+--------+-------+
+| id | style | color | owner |
++----+-------+--------+-------+
+| 4 | dress | orange | 2 |
+| 5 | polo | red | 2 |
+| 6 | dress | blue | 2 |
++----+-------+--------+-------+
+@end example
+
+@findex UNION
+@node Searching on two keys, Database use, Examples, Tutorial
+@section Searching on two keys
+
+@strong{MySQL} doesn't yet optimize when you search on two different
+keys combined with @code{OR} (Searching on one key with different @code{OR}
+parts is optimized quite good):
+
+@example
+SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1'
+OR field2_index = '1'
+@end example
+
+The reason is that we haven't yet had time to come up with an efficient
+way to handle this in the general case. (The @code{AND} handling is
+in comparison now completely general and works very well).
+
+For the moment you can solve this very efficently by using a
+@code{TEMPORARY} table; This type of optimization is also very good if
+you are using very complicated queries where the SQL server does the
+optimizations in the wrong order.
+
+@example
+CREATE TEMPORARY TABLE tmp
+SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1';
+INSERT INTO tmp
+SELECT field1_index, field2_index FROM test_table WHERE field2_index = '1';
+SELECT * from tmp;
+DROP TABLE tmp;
+@end example
+
+The above way to solve this query is in effect an @code{UNION} of two queries.
+
+@node Database use, Getting information, Searching on two keys, Tutorial
+@section Creating and using a database
+
+@menu
+* Creating database:: Creating a database
+* Creating tables:: Creating a table
+* Loading tables:: Loading data into a table
+* Retrieving data:: Retrieving information from a table
+* Multiple tables:: Using more than one table
+@end menu
+
+Now that you know how to enter commands, it's time to access a database.
+
+Suppose you have several pets in your home (your ``menagerie'') and you'd
+like to keep track of various types of information about them. You can do so
+by creating tables to hold your data and loading them with the desired
+information. Then you can answer different sorts of questions about your
+animals by retrieving data from the tables. This section shows how to do
+all that:
+
+@itemize @bullet
+@item
+How to create a database
+@item
+How to create a table
+@item
+How to load data into the table
+@item
+How to retrieve data from the table in various ways
+@item
+How to use multiple tables
+@end itemize
+
+The menagerie database will be simple (deliberately), but it is not difficult
+to think of real-world situations in which a similar type of database might
+be used. For example, a database like this could be used by a farmer to keep
+track of livestock, or by a veterinarian to keep track of patient records.
+
+Use the @code{SHOW} statement to find out what databases currently exist
+on the server:
+
+@example
+mysql> SHOW DATABASES;
++----------+
+| Database |
++----------+
+| mysql |
+| test |
+| tmp |
++----------+
+@end example
+
+The list of databases is probably different on your machine, but the
+@code{mysql} and @code{test} databases are likely to be among them. The
+@code{mysql} database is required because it describes user access
+privileges. The @code{test} database is often provided as a workspace for
+users to try things out.
+
+If the @code{test} database exists, try to access it:
+
+@example
+mysql> USE test
+Database changed
+@end example
+
+Note that @code{USE}, like @code{QUIT}, does not require a semicolon. (You
+can terminate such statements with a semicolon if you like; it does no harm.)
+The @code{USE} statement is special in another way, too: it must be given on
+a single line.
+
+You can use the @code{test} database (if you have access to it) for the
+examples that follow, but anything you create in that database can be
+removed by anyone else with access to it. For this reason, you should
+probably ask your @strong{MySQL} administrator for permission to use a
+database of your own. Suppose you want to call yours @code{menagerie}. The
+administrator needs to execute a command like this:
+
+@example
+mysql> GRANT ALL ON menagerie.* TO your_mysql_name;
+@end example
+
+where @code{your_mysql_name} is the @strong{MySQL} user name assigned to
+you.
+
+@node Creating database, Creating tables, Database use, Database use
+@subsection Creating and selecting a database
+
+If the administrator creates your database for you when setting up your
+permissions, you can begin using it. Otherwise, you need to create it
+yourself:
+
+@example
+mysql> CREATE DATABASE menagerie;
+@end example
+
+Under Unix, database names are case sensitive (unlike SQL keywords), so you
+must always refer to your database as @code{menagerie}, not as
+@code{Menagerie}, @code{MENAGERIE} or some other variant. This is also true
+for table names. (Under Windows, this restriction does not apply, although
+you must refer to databases and tables using the same lettercase throughout a
+given query.)
+
+Creating a database does not select it for use, you must do that explicitly.
+To make @code{menagerie} the current database, use this command:
+
+@example
+mysql> USE menagerie
+Database changed
+@end example
+
+Your database needs to be created only once, but you must select it for use
+each time you begin a @code{mysql} session. You can do this by issuing a
+@code{USE} statement as shown above. Alternatively, you can select the
+database on the command line when you invoke @code{mysql}. Just specify its
+name after any connection parameters that you might need to provide. For
+example:
+
+@example
+shell> mysql -h host -u user -p menagerie
+Enter password: ********
+@end example
+
+Note that @code{menagerie} is not your password on the command just shown.
+If you want to supply your password on the command line after the @code{-p}
+option, you must do so with no intervening space (e.g., as
+@code{-pmypassword}, not as @code{-p mypassword}). However, putting your
+password on the command line is not recommended, because doing so exposes it
+to snooping by other users logged in on your machine.
+
+@node Creating tables, Loading tables, Creating database, Database use
+@subsection Creating a table
+
+Creating the database is the easy part, but at this point it's empty, as
+@code{SHOW TABLES} will tell you:
+
+@example
+mysql> SHOW TABLES;
+Empty set (0.00 sec)
+@end example
+
+The harder part is deciding what the structure of your database should be:
+what tables you will need, and what columns will be in each of them.
+
+You'll want a table that contains a record for each of your pets. This can
+be called the @code{pet} table, and it should contain, as a bare minimum,
+each animal's name. Because the name by itself is not very interesting, the
+table should contain other information. For example, if more than one person
+in your family keeps pets, you might want to list each animal's owner. You
+might also want to record some basic descriptive information such as species
+and sex.
+
+How about age? That might be of interest, but it's not a good thing to store
+in a database. Age changes as time passes, which means you'd have to update
+your records often. Instead, it's better to store a fixed value such as
+date of birth. Then, whenever you need age, you can calculate it as the
+difference between the current date and the birth date. @strong{MySQL}
+provides functions for doing date arithmetic, so this is not difficult.
+Storing birth date rather than age has other advantages, too:
+
+@itemize @bullet
+@item
+You can use the database for tasks such as generating reminders for upcoming
+pet birthdays. (If you think this type of query is somewhat silly, note that
+it is the same question you might ask in the context of a business database
+to identify clients to whom you'll soon need to send out birthday greetings,
+for that computer-assisted personal touch.)
+
+@item
+You can calculate age in relation to dates other than the current date. For
+example, if you store death date in the database, you can easily calculate
+how old a pet was when it died.
+@end itemize
+
+You can probably think of other types of information that would be useful in
+the @code{pet} table, but the ones identified so far are sufficient for now:
+name, owner, species, sex, birth and death.
+
+Use a @code{CREATE TABLE} statement to specify the layout of your table:
+
+@example
+mysql> CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20),
+ -> species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);
+@end example
+
+@code{VARCHAR} is a good choice for the @code{name}, @code{owner} and
+@code{species} columns because the column values will vary in length. The
+lengths of those columns need not all be the same, and need not be
+@code{20}. You can pick any length from @code{1} to @code{255}, whatever
+seems most reasonable to you. (If you make a poor choice and it turns
+out later that you need a longer field, @strong{MySQL} provides an
+@code{ALTER TABLE} statement.)
+
+Animal sex can be represented in a variety of ways, for example, @code{"m"}
+and @code{"f"}, or perhaps @code{"male"} and @code{"female"}. It's simplest
+to use the single characters @code{"m"} and @code{"f"}.
+
+The use of the @code{DATE} data type for the @code{birth} and @code{death}
+columns is a fairly obvious choice.
+
+Now that you have created a table, @code{SHOW TABLES} should produce some
+output:
+
+@example
+mysql> SHOW TABLES;
++---------------------+
+| Tables in menagerie |
++---------------------+
+| pet |
++---------------------+
+@end example
+
+To verify that your table was created the way you expected, use
+a @code{DESCRIBE} statement:
+
+@example
+mysql> DESCRIBE pet;
++---------+-------------+------+-----+---------+-------+
+| Field | Type | Null | Key | Default | Extra |
++---------+-------------+------+-----+---------+-------+
+| name | varchar(20) | YES | | NULL | |
+| owner | varchar(20) | YES | | NULL | |
+| species | varchar(20) | YES | | NULL | |
+| sex | char(1) | YES | | NULL | |
+| birth | date | YES | | NULL | |
+| death | date | YES | | NULL | |
++---------+-------------+------+-----+---------+-------+
+@end example
+
+You can use @code{DESCRIBE} any time, for example, if you forget the names of
+the columns in your table or what types they are.
+
+@node Loading tables, Retrieving data, Creating tables, Database use
+@subsection Loading data into a table
+
+After creating your table, you need to populate it. The @code{LOAD DATA} and
+@code{INSERT} statements are useful for this.
+
+Suppose your pet records can be described as shown below.
+(Observe that @strong{MySQL} expects dates in @code{YYYY-MM-DD} format;
+this may be different than what you are used to.)
+
+@multitable @columnfractions .16 .16 .16 .16 .16 .16
+@item @strong{name} @tab @strong{owner} @tab @strong{species} @tab @strong{sex} @tab @strong{birth} @tab @strong{death}
+@item Fluffy @tab Harold @tab cat @tab f @tab 1993-02-04 @tab
+@item Claws @tab Gwen @tab cat @tab m @tab 1994-03-17 @tab
+@item Buffy @tab Harold @tab dog @tab f @tab 1989-05-13 @tab
+@item Fang @tab Benny @tab dog @tab m @tab 1990-08-27 @tab
+@item Bowser @tab Diane @tab dog @tab m @tab 1998-08-31 @tab 1995-07-29
+@item Chirpy @tab Gwen @tab bird @tab f @tab 1998-09-11 @tab
+@item Whistler @tab Gwen @tab bird @tab @tab 1997-12-09 @tab
+@item Slim @tab Benny @tab snake @tab m @tab 1996-04-29 @tab
+@end multitable
+
+Because you are beginning with an empty table, an easy way to populate it is to
+create a text file containing a row for each of your animals, then load the
+contents of the file into the table with a single statement.
+
+You could create a text file @file{pet.txt} containing one record per line,
+with values separated by tabs, and given in the order in which the columns
+were listed in the @code{CREATE TABLE} statement. For missing values (such
+as unknown sexes, or death dates for animals that are still living), you can
+use @code{NULL} values. To represent these in your text file, use
+@code{\N}. For example, the record for Whistler the bird would look like
+this (where the whitespace between values is a single tab character):
+
+@multitable @columnfractions .15 .15 .15 .15 .25 .15
+@item @code{Whistler} @tab @code{Gwen} @tab @code{bird} @tab @code{\N} @tab @code{1997-12-09} @tab @code{\N}
+@end multitable
+
+To load the text file @file{pet.txt} into the @code{pet} table, use this
+command:
+
+@example
+mysql> LOAD DATA LOCAL INFILE "pet.txt" INTO TABLE pet;
+@end example
+
+You can specify the column value separator and end of line marker explicitly
+in the @code{LOAD DATA} statement if you wish, but the defaults are tab and
+linefeed. These are sufficient for the statement to read the file
+@file{pet.txt} properly.
+
+When you want to add new records one at a time, the @code{INSERT} statement
+is useful. In its simplest form, you supply values for each column, in the
+order in which the columns were listed in the @code{CREATE TABLE} statement.
+Suppose Diane gets a new hamster named Puffball. You could add a new record
+using an @code{INSERT} statement like this:
+
+@example
+mysql> INSERT INTO pet
+ -> VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);
+@end example
+
+Note that string and date values are specified as quoted strings here. Also,
+with @code{INSERT}, you can insert @code{NULL} directly to represent a
+missing value. You do not use @code{\N} like you do with @code{LOAD DATA}.
+
+From this example, you should be able to see that there would be a lot more
+typing involved to load
+your records initially using several @code{INSERT} statements rather
+than a single @code{LOAD DATA} statement.
+
+@node Retrieving data, Multiple tables, Loading tables, Database use
+@subsection Retrieving information from a table
+
+@menu
+* Selecting all:: Selecting all data
+* Selecting rows:: Selecting particular rows
+* Selecting columns:: Selecting particular columns
+* Sorting rows:: Sorting rows
+* Date calculations:: Date calculations
+* Working with NULL:: Working with @code{NULL} values
+* Pattern matching:: Pattern matching
+* Counting rows:: Counting rows
+@end menu
+
+The @code{SELECT} statement is used to pull information from a table.
+The general form of the statement is:
+
+@example
+SELECT what_to_select
+FROM which_table
+WHERE conditions_to_satisfy
+@end example
+
+@code{what_to_select} indicates what you want to see. This can be a list of
+columns, or @code{*} to indicate ``all columns.'' @code{which_table}
+indicates the table from which you want to retrieve data. The @code{WHERE}
+clause is optional. If it's present, @code{conditions_to_satisfy} specifies
+conditions that rows must satisfy to qualify for retrieval.
+
+@node Selecting all, Selecting rows, Retrieving data, Retrieving data
+@subsubsection Selecting all data
+
+The simplest form of @code{SELECT} retrieves everything from a table:
+
+@example
+mysql> SELECT * FROM pet;
++----------+--------+---------+------+------------+------------+
+| name | owner | species | sex | birth | death |
++----------+--------+---------+------+------------+------------+
+| Fluffy | Harold | cat | f | 1993-02-04 | NULL |
+| Claws | Gwen | cat | m | 1994-03-17 | NULL |
+| Buffy | Harold | dog | f | 1989-05-13 | NULL |
+| Fang | Benny | dog | m | 1990-08-27 | NULL |
+| Bowser | Diane | dog | m | 1998-08-31 | 1995-07-29 |
+| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
+| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |
+| Slim | Benny | snake | m | 1996-04-29 | NULL |
+| Puffball | Diane | hamster | f | 1999-03-30 | NULL |
++----------+--------+---------+------+------------+------------+
+@end example
+
+This form of @code{SELECT} is useful if you want to review your entire table,
+for instance, after you've just loaded it with your initial dataset. As it
+happens, the output just shown reveals an error in your data file: Bowser
+appears to have been born after he died! Consulting your original pedigree
+papers, you find that the correct birth year is 1989, not 1998.
+
+There are are least a couple of ways to fix this:
+
+@itemize @bullet
+@item
+Edit the file @file{pet.txt} to correct the error, then empty the table
+and reload it using @code{DELETE} and @code{LOAD DATA}:
+
+@example
+mysql> SET AUTOCOMMIT=1; # Used for quick recreate of the table
+mysql> DELETE FROM pet;
+mysql> LOAD DATA LOCAL INFILE "pet.txt" INTO TABLE pet;
+@end example
+
+However, if you do this, you must also re-enter the record for Puffball.
+
+@item
+Fix only the erroneous record with an @code{UPDATE} statement:
+
+@example
+mysql> UPDATE pet SET birth = "1989-08-31" WHERE name = "Bowser";
+@end example
+@end itemize
+
+As shown above, it is easy to retrieve an entire table. But typically you
+don't want to do that, particularly when the table becomes large. Instead,
+you're usually more interested in answering a particular question, in which
+case you specify some constraints on the information you want. Let's look at
+some selection queries in terms of questions about your pets that they
+answer.
+
+@node Selecting rows, Selecting columns, Selecting all, Retrieving data
+@subsubsection Selecting particular rows
+
+You can select only particular rows from your table. For example, if you want
+to verify the change that you made to Bowser's birth date, select Bowser's
+record like this:
+
+@example
+mysql> SELECT * FROM pet WHERE name = "Bowser";
++--------+-------+---------+------+------------+------------+
+| name | owner | species | sex | birth | death |
++--------+-------+---------+------+------------+------------+
+| Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |
++--------+-------+---------+------+------------+------------+
+@end example
+
+The output confirms that the year is correctly recorded now as 1989, not 1998.
+
+String comparisons are normally case-insensitive, so you can specify the
+name as @code{"bowser"}, @code{"BOWSER"}, etc. The query result will be
+the same.
+
+You can specify conditions on any column, not just @code{name}. For example,
+if you want to know which animals were born after 1998, test the @code{birth}
+column:
+
+@example
+mysql> SELECT * FROM pet WHERE birth >= "1998-1-1";
++----------+-------+---------+------+------------+-------+
+| name | owner | species | sex | birth | death |
++----------+-------+---------+------+------------+-------+
+| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
+| Puffball | Diane | hamster | f | 1999-03-30 | NULL |
++----------+-------+---------+------+------------+-------+
+@end example
+
+You can combine conditions, for example, to locate female dogs:
+
+@example
+mysql> SELECT * FROM pet WHERE species = "dog" AND sex = "f";
++-------+--------+---------+------+------------+-------+
+| name | owner | species | sex | birth | death |
++-------+--------+---------+------+------------+-------+
+| Buffy | Harold | dog | f | 1989-05-13 | NULL |
++-------+--------+---------+------+------------+-------+
+@end example
+
+The preceding query uses the @code{AND} logical operator. There is also an
+@code{OR} operator:
+
+@example
+mysql> SELECT * FROM pet WHERE species = "snake" OR species = "bird";
++----------+-------+---------+------+------------+-------+
+| name | owner | species | sex | birth | death |
++----------+-------+---------+------+------------+-------+
+| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
+| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |
+| Slim | Benny | snake | m | 1996-04-29 | NULL |
++----------+-------+---------+------+------------+-------+
+@end example
+
+@code{AND} and @code{OR} may be intermixed. If you do that, it's a good idea
+to use parentheses to indicate how conditions should be grouped:
+
+@example
+mysql> SELECT * FROM pet WHERE (species = "cat" AND sex = "m")
+ -> OR (species = "dog" AND sex = "f");
++-------+--------+---------+------+------------+-------+
+| name | owner | species | sex | birth | death |
++-------+--------+---------+------+------------+-------+
+| Claws | Gwen | cat | m | 1994-03-17 | NULL |
+| Buffy | Harold | dog | f | 1989-05-13 | NULL |
++-------+--------+---------+------+------------+-------+
+@end example
+
+@node Selecting columns, Sorting rows, Selecting rows, Retrieving data
+@subsubsection Selecting particular columns
+
+
+If you don't want to see entire rows from your table, just name the columns
+in which you're interested, separated by commas. For example, if you want to
+know when your animals were born, select the @code{name} and @code{birth}
+columns:
+
+@example
+mysql> SELECT name, birth FROM pet;
++----------+------------+
+| name | birth |
++----------+------------+
+| Fluffy | 1993-02-04 |
+| Claws | 1994-03-17 |
+| Buffy | 1989-05-13 |
+| Fang | 1990-08-27 |
+| Bowser | 1989-08-31 |
+| Chirpy | 1998-09-11 |
+| Whistler | 1997-12-09 |
+| Slim | 1996-04-29 |
+| Puffball | 1999-03-30 |
++----------+------------+
+@end example
+
+To find out who owns pets, use this query:
+
+@example
+mysql> SELECT owner FROM pet;
++--------+
+| owner |
++--------+
+| Harold |
+| Gwen |
+| Harold |
+| Benny |
+| Diane |
+| Gwen |
+| Gwen |
+| Benny |
+| Diane |
++--------+
+@end example
+
+@findex DISTINCT
+However, notice that the query simply retrieves the @code{owner} field from
+each record, and some of them appear more than once. To minimize the output,
+retrieve each unique output record just once by adding the keyword
+@code{DISTINCT}:
+
+@example
+mysql> SELECT DISTINCT owner FROM pet;
++--------+
+| owner |
++--------+
+| Benny |
+| Diane |
+| Gwen |
+| Harold |
++--------+
+@end example
+
+You can use a @code{WHERE} clause to combine row selection with column
+selection. For example, to get birth dates for dogs and cats only,
+use this query:
+
+@example
+mysql> SELECT name, species, birth FROM pet
+ -> WHERE species = "dog" OR species = "cat";
++--------+---------+------------+
+| name | species | birth |
++--------+---------+------------+
+| Fluffy | cat | 1993-02-04 |
+| Claws | cat | 1994-03-17 |
+| Buffy | dog | 1989-05-13 |
+| Fang | dog | 1990-08-27 |
+| Bowser | dog | 1989-08-31 |
++--------+---------+------------+
+@end example
+
+@node Sorting rows, Date calculations, Selecting columns, Retrieving data
+@subsubsection Sorting rows
+
+You may have noticed in the preceding examples that the result rows are
+displayed in no particular order. However, it's often easier to examine
+query output when the rows are sorted in some meaningful way. To sort a
+result, use an @code{ORDER BY} clause.
+
+Here are animal birthdays, sorted by date:
+
+@example
+mysql> SELECT name, birth FROM pet ORDER BY birth;
++----------+------------+
+| name | birth |
++----------+------------+
+| Buffy | 1989-05-13 |
+| Bowser | 1989-08-31 |
+| Fang | 1990-08-27 |
+| Fluffy | 1993-02-04 |
+| Claws | 1994-03-17 |
+| Slim | 1996-04-29 |
+| Whistler | 1997-12-09 |
+| Chirpy | 1998-09-11 |
+| Puffball | 1999-03-30 |
++----------+------------+
+@end example
+
+To sort in reverse order, add the @code{DESC} (descending) keyword to the
+name of the column you are sorting by:
+
+@example
+mysql> SELECT name, birth FROM pet ORDER BY birth DESC;
++----------+------------+
+| name | birth |
++----------+------------+
+| Puffball | 1999-03-30 |
+| Chirpy | 1998-09-11 |
+| Whistler | 1997-12-09 |
+| Slim | 1996-04-29 |
+| Claws | 1994-03-17 |
+| Fluffy | 1993-02-04 |
+| Fang | 1990-08-27 |
+| Bowser | 1989-08-31 |
+| Buffy | 1989-05-13 |
++----------+------------+
+@end example
+
+You can sort on multiple columns. For example, to sort by type of
+animal, then by birth date within animal type with youngest animals first,
+use the following query:
+
+@example
+mysql> SELECT name, species, birth FROM pet ORDER BY species, birth DESC;
++----------+---------+------------+
+| name | species | birth |
++----------+---------+------------+
+| Chirpy | bird | 1998-09-11 |
+| Whistler | bird | 1997-12-09 |
+| Claws | cat | 1994-03-17 |
+| Fluffy | cat | 1993-02-04 |
+| Fang | dog | 1990-08-27 |
+| Bowser | dog | 1989-08-31 |
+| Buffy | dog | 1989-05-13 |
+| Puffball | hamster | 1999-03-30 |
+| Slim | snake | 1996-04-29 |
++----------+---------+------------+
+@end example
+
+Note that the @code{DESC} keyword applies only to the column name immediately
+preceding it (@code{birth}); @code{species} values are still sorted in
+ascending order.
+
+@node Date calculations, Working with NULL, Sorting rows, Retrieving data
+@subsubsection Date calculations
+
+@strong{MySQL} provides several functions that you can use to perform
+calculations on dates, for example, to calculate ages or extract
+parts of dates.
+
+To determine how many years old each of your pets is, compute age as the
+difference between the birth date and the current date. Do this by
+converting the two dates to days, take the difference, and divide by 365 (the
+number of days in a year):
+
+@example
+mysql> SELECT name, (TO_DAYS(NOW())-TO_DAYS(birth))/365 FROM pet;
++----------+-------------------------------------+
+| name | (TO_DAYS(NOW())-TO_DAYS(birth))/365 |
++----------+-------------------------------------+
+| Fluffy | 6.15 |
+| Claws | 5.04 |
+| Buffy | 9.88 |
+| Fang | 8.59 |
+| Bowser | 9.58 |
+| Chirpy | 0.55 |
+| Whistler | 1.30 |
+| Slim | 2.92 |
+| Puffball | 0.00 |
++----------+-------------------------------------+
+@end example
+
+Although the query works, there are some things about it that could be
+improved. First, the result could be scanned more easily if the rows were
+presented in some order. Second, the heading for the age column isn't very
+meaningful.
+
+The first problem can be handled by adding an @code{ORDER BY name} clause to
+sort the output by name. To deal with the column heading, provide a name for
+the column so that a different label appears in the output (this is called a
+column alias):
+
+@example
+mysql> SELECT name, (TO_DAYS(NOW())-TO_DAYS(birth))/365 AS age
+ -> FROM pet ORDER BY name;
++----------+------+
+| name | age |
++----------+------+
+| Bowser | 9.58 |
+| Buffy | 9.88 |
+| Chirpy | 0.55 |
+| Claws | 5.04 |
+| Fang | 8.59 |
+| Fluffy | 6.15 |
+| Puffball | 0.00 |
+| Slim | 2.92 |
+| Whistler | 1.30 |
++----------+------+
+@end example
+
+To sort the output by @code{age} rather than @code{name}, just use a
+different @code{ORDER BY} clause:
+
+@example
+mysql> SELECT name, (TO_DAYS(NOW())-TO_DAYS(birth))/365 AS age
+ -> FROM pet ORDER BY age;
++----------+------+
+| name | age |
++----------+------+
+| Puffball | 0.00 |
+| Chirpy | 0.55 |
+| Whistler | 1.30 |
+| Slim | 2.92 |
+| Claws | 5.04 |
+| Fluffy | 6.15 |
+| Fang | 8.59 |
+| Bowser | 9.58 |
+| Buffy | 9.88 |
++----------+------+
+@end example
+
+A similar query can be used to determine age at death for animals that have
+died. You determine which animals these are by checking whether or not the
+@code{death} value is @code{NULL}. Then, for those with non-@code{NULL}
+values, compute the difference between the @code{death} and @code{birth}
+values:
+
+@example
+mysql> SELECT name, birth, death, (TO_DAYS(death)-TO_DAYS(birth))/365 AS age
+ -> FROM pet WHERE death IS NOT NULL ORDER BY age;
++--------+------------+------------+------+
+| name | birth | death | age |
++--------+------------+------------+------+
+| Bowser | 1989-08-31 | 1995-07-29 | 5.91 |
++--------+------------+------------+------+
+@end example
+
+The query uses @code{death IS NOT NULL} rather than @code{death != NULL}
+because @code{NULL} is a special value. This is explained later.
+@xref{Working with NULL, , Working with @code{NULL}}.
+
+What if you want to know which animals have birthdays next month? For this
+type of calculation, year and day are irrelevant, you simply want to extract
+the month part of the @code{birth} column. @strong{MySQL} provides several
+date-part extraction functions, such as @code{YEAR()}, @code{MONTH()} and
+@code{DAYOFMONTH()}. @code{MONTH()} is the appropriate function here. To
+see how it works, run a simple query that displays the value of both
+@code{birth} and @code{MONTH(birth)}:
+
+@example
+mysql> SELECT name, birth, MONTH(birth) FROM pet;
++----------+------------+--------------+
+| name | birth | MONTH(birth) |
++----------+------------+--------------+
+| Fluffy | 1993-02-04 | 2 |
+| Claws | 1994-03-17 | 3 |
+| Buffy | 1989-05-13 | 5 |
+| Fang | 1990-08-27 | 8 |
+| Bowser | 1989-08-31 | 8 |
+| Chirpy | 1998-09-11 | 9 |
+| Whistler | 1997-12-09 | 12 |
+| Slim | 1996-04-29 | 4 |
+| Puffball | 1999-03-30 | 3 |
++----------+------------+--------------+
+@end example
+
+Finding animals with birthdays in the upcoming month is easy, too. Suppose
+the current month is April. Then the month value is @code{4} and you look
+for animals born in May (month 5) like this:
+
+@example
+mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5;
++-------+------------+
+| name | birth |
++-------+------------+
+| Buffy | 1989-05-13 |
++-------+------------+
+@end example
+
+There is a small complication if the current month is December, of course.
+You don't just add one to the month number (@code{12}) and look for animals
+born in month 13, because there is no such month. Instead, you look for
+animals born in January (month 1).
+
+You can even write the query so that it works no matter what the current
+month is. That way you don't have to use a particular month number
+in the query. @code{DATE_ADD()} allows you to add a time interval to a
+given date. If you add a month to the value of @code{NOW()}, then extract
+the month part with @code{MONTH()}, the result produces the month in which to
+look for birthdays:
+
+@example
+mysql> SELECT name, birth FROM pet
+ -> WHERE MONTH(birth) = MONTH(DATE_ADD(NOW(), INTERVAL 1 MONTH));
+@end example
+
+A different way to accomplish the same task is to add @code{1} to get the
+next month after the current one (after using the modulo function (@code{MOD})
+to ``wrap around'' the month value to @code{0} if it is currently
+@code{12}):
+
+@example
+mysql> SELECT name, birth FROM pet
+ -> WHERE MONTH(birth) = MOD(MONTH(NOW()), 12) + 1;
+@end example
+
+Note that @code{MONTH} return a number between 1 and 12. And
+@code{MOD(something,12)} returns a number between 0 and 11. So the
+addition has to be after the @code{MOD()} oterwise we would go from
+November (11) to January (1).
+
+@node Working with NULL, Pattern matching, Date calculations, Retrieving data
+@subsubsection Working with @code{NULL} values
+
+The @code{NULL} value can be surprising until you get used to it.
+Conceptually, @code{NULL} means ``missing value'' or ``unknown value'' and it
+is treated somewhat differently than other values. To test for @code{NULL},
+you cannot use the arithmetic comparison operators such as @code{=}, @code{<}
+or @code{!=}. To demonstrate this for yourself, try the following query:
+
+@example
+mysql> SELECT 1 = NULL, 1 != NULL, 1 < NULL, 1 > NULL;
++----------+-----------+----------+----------+
+| 1 = NULL | 1 != NULL | 1 < NULL | 1 > NULL |
++----------+-----------+----------+----------+
+| NULL | NULL | NULL | NULL |
++----------+-----------+----------+----------+
+@end example
+
+Clearly you get no meaningful results from these comparisons. Use
+the @code{IS NULL} and @code{IS NOT NULL} operators instead:
+
+@example
+mysql> SELECT 1 IS NULL, 1 IS NOT NULL;
++-----------+---------------+
+| 1 IS NULL | 1 IS NOT NULL |
++-----------+---------------+
+| 0 | 1 |
++-----------+---------------+
+@end example
+
+In @strong{MySQL}, 0 means false and 1 means true.
+
+This special treatment of @code{NULL} is why, in the previous section, it
+was necessary to determine which animals are no longer alive using
+@code{death IS NOT NULL} instead of @code{death != NULL}.
+
+@node Pattern matching, Counting rows, Working with NULL, Retrieving data
+@subsubsection Pattern matching
+
+@strong{MySQL} provides standard SQL pattern matching as well as a form of
+pattern matching based on extended regular expressions similar to those used
+by Unix utilities such as @code{vi}, @code{grep} and @code{sed}.
+
+SQL pattern matching allows you to use @samp{_} to match any single
+character, and @samp{%} to match an arbitrary number of characters (including
+zero characters). In @strong{MySQL}, SQL patterns are case insensitive by
+default. Some examples are shown below. Note that you do not use @code{=}
+or @code{!=} when you use SQL patterns; use the @code{LIKE} or @code{NOT
+LIKE} comparison operators instead.
+
+To find names beginning with @samp{b}:
+
+@example
+mysql> SELECT * FROM pet WHERE name LIKE "b%";
++--------+--------+---------+------+------------+------------+
+| name | owner | species | sex | birth | death |
++--------+--------+---------+------+------------+------------+
+| Buffy | Harold | dog | f | 1989-05-13 | NULL |
+| Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |
++--------+--------+---------+------+------------+------------+
+@end example
+
+To find names ending with @samp{fy}:
+
+@example
+mysql> SELECT * FROM pet WHERE name LIKE "%fy";
++--------+--------+---------+------+------------+-------+
+| name | owner | species | sex | birth | death |
++--------+--------+---------+------+------------+-------+
+| Fluffy | Harold | cat | f | 1993-02-04 | NULL |
+| Buffy | Harold | dog | f | 1989-05-13 | NULL |
++--------+--------+---------+------+------------+-------+
+@end example
+
+To find names containing a @samp{w}:
+
+@example
+mysql> SELECT * FROM pet WHERE name LIKE "%w%";
++----------+-------+---------+------+------------+------------+
+| name | owner | species | sex | birth | death |
++----------+-------+---------+------+------------+------------+
+| Claws | Gwen | cat | m | 1994-03-17 | NULL |
+| Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |
+| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |
++----------+-------+---------+------+------------+------------+
+@end example
+
+To find names containing exactly five characters, use the @samp{_} pattern
+character:
+
+@example
+mysql> SELECT * FROM pet WHERE name LIKE "_____";
++-------+--------+---------+------+------------+-------+
+| name | owner | species | sex | birth | death |
++-------+--------+---------+------+------------+-------+
+| Claws | Gwen | cat | m | 1994-03-17 | NULL |
+| Buffy | Harold | dog | f | 1989-05-13 | NULL |
++-------+--------+---------+------+------------+-------+
+@end example
+
+The other type of pattern matching provided by @strong{MySQL} uses extended
+regular expressions. When you test for a match for this type of pattern, use
+the @code{REGEXP} and @code{NOT REGEXP} operators (or @code{RLIKE} and
+@code{NOT RLIKE}, which are synonyms).
+
+Some characteristics of extended regular expressions are:
+
+@itemize @bullet
+@item
+@samp{.} matches any single character.
+
+@item
+A character class @samp{[...]} matches any character within the brackets.
+For example, @samp{[abc]} matches @samp{a}, @samp{b} or @samp{c}. To name a
+range of characters, use a dash. @samp{[a-z]} matches any lowercase letter,
+whereas @samp{[0-9]} matches any digit.
+
+@item
+@samp{*} matches zero or more instances of the thing preceding it. For
+example, @samp{x*} matches any number of @samp{x} characters,
+@samp{[0-9]*} matches any number of digits, and @samp{.*} matches any
+number of anything.
+
+@item
+Regular expressions are case sensitive, but you can use a character class to
+match both lettercases if you wish. For example, @samp{[aA]} matches
+lowercase or uppercase @samp{a} and @samp{[a-zA-Z]} matches any letter in
+either case.
+
+@item
+The pattern matches if it occurs anywhere in the value being tested
+(SQL patterns match only if they match the entire value).
+
+@item
+To anchor a pattern so that it must match the beginning or end of the value
+being tested, use @samp{^} at the beginning or @samp{$} at the end of the
+pattern.
+@end itemize
+
+To demonstrate how extended regular expressions work, the @code{LIKE} queries
+shown above are rewritten below to use @code{REGEXP}:
+
+To find names beginning with @samp{b}, use @samp{^} to match the beginning of
+the name and @samp{[bB]} to match either lowercase or uppercase @samp{b}:
+
+@example
+mysql> SELECT * FROM pet WHERE name REGEXP "^[bB]";
++--------+--------+---------+------+------------+------------+
+| name | owner | species | sex | birth | death |
++--------+--------+---------+------+------------+------------+
+| Buffy | Harold | dog | f | 1989-05-13 | NULL |
+| Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |
++--------+--------+---------+------+------------+------------+
+@end example
+
+To find names ending with @samp{fy}, use @samp{$} to match the end of the
+name:
+
+@example
+mysql> SELECT * FROM pet WHERE name REGEXP "fy$";
++--------+--------+---------+------+------------+-------+
+| name | owner | species | sex | birth | death |
++--------+--------+---------+------+------------+-------+
+| Fluffy | Harold | cat | f | 1993-02-04 | NULL |
+| Buffy | Harold | dog | f | 1989-05-13 | NULL |
++--------+--------+---------+------+------------+-------+
+@end example
+
+To find names containing a @samp{w}, use
+@samp{[wW]} to match either lowercase or uppercase @samp{w}:
+
+@example
+mysql> SELECT * FROM pet WHERE name REGEXP "[wW]";
++----------+-------+---------+------+------------+------------+
+| name | owner | species | sex | birth | death |
++----------+-------+---------+------+------------+------------+
+| Claws | Gwen | cat | m | 1994-03-17 | NULL |
+| Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |
+| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |
++----------+-------+---------+------+------------+------------+
+@end example
+
+Because a regular expression pattern matches if it occurs anywhere in the
+value, it is not necessary in the previous query to put a wildcard on either
+side of the pattern to get it to match the entire value like it would be if
+you used a SQL pattern.
+
+To find names containing exactly five characters, use @samp{^} and @samp{$}
+to match the beginning and end of the name, and five instances of @samp{.}
+in between:
+
+@example
+mysql> SELECT * FROM pet WHERE name REGEXP "^.....$";
++-------+--------+---------+------+------------+-------+
+| name | owner | species | sex | birth | death |
++-------+--------+---------+------+------------+-------+
+| Claws | Gwen | cat | m | 1994-03-17 | NULL |
+| Buffy | Harold | dog | f | 1989-05-13 | NULL |
++-------+--------+---------+------+------------+-------+
+@end example
+
+You could also write the previous query using the @samp{@{n@}}
+``repeat-@code{n}-times'' operator:
+
+@example
+mysql> SELECT * FROM pet WHERE name REGEXP "^.@{5@}$";
++-------+--------+---------+------+------------+-------+
+| name | owner | species | sex | birth | death |
++-------+--------+---------+------+------------+-------+
+| Claws | Gwen | cat | m | 1994-03-17 | NULL |
+| Buffy | Harold | dog | f | 1989-05-13 | NULL |
++-------+--------+---------+------+------------+-------+
+@end example
+
+@node Counting rows, , Pattern matching, Retrieving data
+@subsubsection Counting rows
+
+Databases are often used to answer the question, ``How often does a certain
+type of data occur in a table?'' For example, you might want to know how
+many pets you have, or how many pets each owner has, or you might want to
+perform various kinds of censuses on your animals.
+
+Counting the total number of animals you have is the same question as ``How
+many rows are in the @code{pet} table?,'' because there is one record per pet.
+The @code{COUNT()} function counts the number of non-@code{NULL} results, so
+the query to count your animals looks like this:
+
+@example
+mysql> SELECT COUNT(*) FROM pet;
++----------+
+| COUNT(*) |
++----------+
+| 9 |
++----------+
+@end example
+
+Earlier, you retrieved the names of the people who owned pets. You can
+use @code{COUNT()} if you want to find out how many pets each owner has:
+
+@example
+mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;
++--------+----------+
+| owner | COUNT(*) |
++--------+----------+
+| Benny | 2 |
+| Diane | 2 |
+| Gwen | 3 |
+| Harold | 2 |
++--------+----------+
+@end example
+
+Note the use of @code{GROUP BY} to group together all records for each
+@code{owner}. Without it, all you get is an error message:
+
+@example
+mysql> SELECT owner, COUNT(owner) FROM pet;
+ERROR 1140 at line 1: Mixing of GROUP columns (MIN(),MAX(),COUNT()...)
+with no GROUP columns is illegal if there is no GROUP BY clause
+@end example
+
+@code{COUNT()} and @code{GROUP BY} are useful for characterizing your
+data in various ways. The following examples show different ways to
+perform animal census operations.
+
+Number of animals per species:
+
+@example
+mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;
++---------+----------+
+| species | COUNT(*) |
++---------+----------+
+| bird | 2 |
+| cat | 2 |
+| dog | 3 |
+| hamster | 1 |
+| snake | 1 |
++---------+----------+
+@end example
+
+Number of animals per sex:
+
+@example
+mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;
++------+----------+
+| sex | COUNT(*) |
++------+----------+
+| NULL | 1 |
+| f | 4 |
+| m | 4 |
++------+----------+
+@end example
+
+(In this output, @code{NULL} indicates ``sex unknown.'')
+
+Number of animals per combination of species and sex:
+
+@example
+mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex;
++---------+------+----------+
+| species | sex | COUNT(*) |
++---------+------+----------+
+| bird | NULL | 1 |
+| bird | f | 1 |
+| cat | f | 1 |
+| cat | m | 1 |
+| dog | f | 1 |
+| dog | m | 2 |
+| hamster | f | 1 |
+| snake | m | 1 |
++---------+------+----------+
+@end example
+
+You need not retrieve an entire table when you use @code{COUNT()}. For
+example, the previous query, when performed just on dogs and cats, looks like
+this:
+
+@example
+mysql> SELECT species, sex, COUNT(*) FROM pet
+ -> WHERE species = "dog" OR species = "cat"
+ -> GROUP BY species, sex;
++---------+------+----------+
+| species | sex | COUNT(*) |
++---------+------+----------+
+| cat | f | 1 |
+| cat | m | 1 |
+| dog | f | 1 |
+| dog | m | 2 |
++---------+------+----------+
+@end example
+
+Or, if you wanted the number of animals per sex only for known-sex animals:
+
+@example
+mysql> SELECT species, sex, COUNT(*) FROM pet
+ -> WHERE sex IS NOT NULL
+ -> GROUP BY species, sex;
++---------+------+----------+
+| species | sex | COUNT(*) |
++---------+------+----------+
+| bird | f | 1 |
+| cat | f | 1 |
+| cat | m | 1 |
+| dog | f | 1 |
+| dog | m | 2 |
+| hamster | f | 1 |
+| snake | m | 1 |
++---------+------+----------+
+@end example
+
+@node Multiple tables, , Retrieving data, Database use
+@subsection Using more than one table
+
+The @code{pet} table keeps track of which pets you have. If you want to
+record other information about them, such as events in their lives like
+visits to the vet or when litters are born, you need another table. What
+should this table look like?
+
+@itemize @bullet
+@item
+It needs to contain the pet name so you know which animal each event pertains
+to.
+
+@item
+It needs a date so you know when the event occurred.
+
+@item
+It needs a field to describe the event.
+
+@item
+If you want to be able to categorize events, it would be useful to have an
+event type field.
+@end itemize
+
+Given these considerations, the @code{CREATE TABLE} statement for the
+@code{event} table might look like this:
+
+@example
+mysql> CREATE TABLE event (name VARCHAR(20), date DATE,
+ -> type VARCHAR(15), remark VARCHAR(255));
+@end example
+
+As with the @code{pet} table, it's easiest to load the initial records
+by creating a tab-delimited text file containing the information:
+
+@multitable @columnfractions .15 .15 .15 .55
+@item Fluffy @tab 1995-05-15 @tab litter @tab 4 kittens, 3 female, 1 male
+@item Buffy @tab 1993-06-23 @tab litter @tab 5 puppies, 2 female, 3 male
+@item Buffy @tab 1994-06-19 @tab litter @tab 3 puppies, 3 female
+@item Chirpy @tab 1999-03-21 @tab vet @tab needed beak straightened
+@item Slim @tab 1997-08-03 @tab vet @tab broken rib
+@item Bowser @tab 1991-10-12 @tab kennel
+@item Fang @tab 1991-10-12 @tab kennel
+@item Fang @tab 1998-08-28 @tab birthday @tab Gave him a new chew toy
+@item Claws @tab 1998-03-17 @tab birthday @tab Gave him a new flea collar
+@item Whistler @tab 1998-12-09 @tab birthday @tab First birthday
+@end multitable
+
+Load the records like this:
+
+@example
+mysql> LOAD DATA LOCAL INFILE "event.txt" INTO TABLE event;
+@end example
+
+Based on what you've learned from the queries you've run on the @code{pet}
+table, you should be able to perform retrievals on the records in the
+@code{event} table; the principles are the same. But when is the
+@code{event} table by itself insufficient to answer questions you might ask?
+
+Suppose you want to find out the ages of each pet when they had their
+litters. The @code{event} table indicates when this occurred, but to
+calculate age of the mother, you need her birth date. Because that is
+stored in the @code{pet} table, you need both tables for the query:
+
+@example
+mysql> SELECT pet.name, (TO_DAYS(date) - TO_DAYS(birth))/365 AS age, remark
+ -> FROM pet, event
+ -> WHERE pet.name = event.name AND type = "litter";
++--------+------+-----------------------------+
+| name | age | remark |
++--------+------+-----------------------------+
+| Fluffy | 2.27 | 4 kittens, 3 female, 1 male |
+| Buffy | 4.12 | 5 puppies, 2 female, 3 male |
+| Buffy | 5.10 | 3 puppies, 3 female |
++--------+------+-----------------------------+
+@end example
+
+There are several things to note about this query:
+
+@itemize @bullet
+@item
+The @code{FROM} clause lists two tables because the query needs to pull
+information from both of them.
+
+@item
+When combining (joining) information from multiple tables, you need to
+specify how records in one table can be matched to records in the other.
+This is easy because they both have a @code{name} column. The query uses
+@code{WHERE} clause to match up records in the two tables based on the
+@code{name} values.
+
+@item
+Because the @code{name} column occurs in both tables, you must be specific
+about which table you mean when referring to the column. This is done
+by prepending the table name to the column name.
+@end itemize
+
+You need not have two different tables to perform a join. Sometimes it is
+useful to join a table to itself, if you want to compare records in a table
+to other records in that same table. For example, to find breeding pairs
+among your pets, you can join the @code{pet} table with itself to pair up
+males and females of like species:
+
+@example
+mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species
+ -> FROM pet AS p1, pet AS p2
+ -> WHERE p1.species = p2.species AND p1.sex = "f" AND p2.sex = "m";
++--------+------+--------+------+---------+
+| name | sex | name | sex | species |
++--------+------+--------+------+---------+
+| Fluffy | f | Claws | m | cat |
+| Buffy | f | Fang | m | dog |
+| Buffy | f | Bowser | m | dog |
++--------+------+--------+------+---------+
+@end example
+
+In this query, we specify aliases for the table name in order to be able
+to refer to the columns and keep straight which instance of the table
+each column reference is associated with.
+
+@node Getting information, Batch mode, Database use, Tutorial
+@section Getting information about databases and tables
+
+What if you forget the name of a database or table, or what the structure of
+a given table is (e.g., what its columns are called)? @strong{MySQL}
+addresses this problem through several statements that provide information
+about the databases and tables it supports.
+
+You have already seen @code{SHOW DATABASES}, which lists the databases
+managed by the server. To find out which database is currently selected,
+use the @code{DATABASE()} function:
+
+@example
+mysql> SELECT DATABASE();
++------------+
+| DATABASE() |
++------------+
+| menagerie |
++------------+
+@end example
+
+If you haven't selected any database yet, the result is blank.
+
+To find out what tables the current database contains (for example, when
+you're not sure about the name of a table), use this command:
+
+@example
+mysql> SHOW TABLES;
++---------------------+
+| Tables in menagerie |
++---------------------+
+| event |
+| pet |
++---------------------+
+@end example
+
+If you want to find out about the structure of a table, the @code{DESCRIBE}
+command is useful; it displays information about each of a table's columns:
+
+@example
+mysql> DESCRIBE pet;
++---------+-------------+------+-----+---------+-------+
+| Field | Type | Null | Key | Default | Extra |
++---------+-------------+------+-----+---------+-------+
+| name | varchar(20) | YES | | NULL | |
+| owner | varchar(20) | YES | | NULL | |
+| species | varchar(20) | YES | | NULL | |
+| sex | char(1) | YES | | NULL | |
+| birth | date | YES | | NULL | |
+| death | date | YES | | NULL | |
++---------+-------------+------+-----+---------+-------+
+@end example
+
+@code{Field} indicates the column name, @code{Type} is the data type for
+the column, @code{Null} indicates whether or not the column can contain
+@code{NULL} values, @code{Key} indicates whether or not the column is
+indexed and @code{Default} specifies the column's default value.
+
+If you have indexes on a table,
+@code{SHOW INDEX FROM tbl_name} produces information about them.
+
+@node Batch mode, Twin, Getting information, Tutorial
+@section Using @code{mysql} in batch mode
+
+In the previous sections, you used @code{mysql} interactively to enter
+queries and view the results. You can also run @code{mysql} in batch
+mode. To do this, put the commands you want to run in a file, then
+tell @code{mysql} to read its input from the file:
+
+@example
+shell> mysql < batch-file
+@end example
+
+If you need to specify connection parameters on the command line, the
+command might look like this:
+
+@example
+shell> mysql -h host -u user -p < batch-file
+Enter password: ********
+@end example
+
+When you use @code{mysql} this way, you are creating a script file, then
+executing the script.
+
+Why use a script? Here are a few reasons:
+
+@itemize @bullet
+@item
+If you run a query repeatedly (say, every day or every week), making it a
+script allows you to avoid retyping it each time you execute it.
+
+@item
+You can generate new queries from existing ones that are similar by copying
+and editing script files.
+
+@item
+Batch mode can also be useful while you're developing a query, particularly
+for multiple-line commands or multiple-statement sequences of commands. If
+you make a mistake, you don't have to retype everything. Just edit your
+script to correct the error, then tell @code{mysql} to execute it again.
+
+@item
+If you have a query that produces a lot of output, you can run the output
+through a pager rather than watching it scroll off the top of your screen:
+
+@example
+shell> mysql < batch-file | more
+@end example
+
+@item
+You can catch the output in a file for further processing:
+
+@example
+shell> mysql < batch-file > mysql.out
+@end example
+
+@item
+You can distribute your script to other people so they can run the commands,
+too.
+
+@item
+Some situations do not allow for interactive use, for example, when you run
+a query from a @code{cron} job. In this case, you must use batch mode.
+@end itemize
+
+The default output format is different (more concise) when you run
+@code{mysql} in batch mode than when you use it interactively. For
+example, the output of @code{SELECT DISTINCT species FROM pet} looks like
+this when run interactively:
+
+@example
++---------+
+| species |
++---------+
+| bird |
+| cat |
+| dog |
+| hamster |
+| snake |
++---------+
+@end example
+
+But like this when run in batch mode:
+
+@example
+species
+bird
+cat
+dog
+hamster
+snake
+@end example
+
+If you want to get the interactive output format in batch mode, use
+@code{mysql -t}. To echo to the output the commands that are executed, use
+@code{mysql -vvv}.
+
+@node Twin, , Batch mode, Tutorial
+@section Queries from twin project
+
+At Analytikerna and Lentus, we have been doing the systems and field work
+for a big research project. This project is a collaboration between the
+Institute of Environmental Medicine at Karolinska Institutet Stockholm
+and the Section on Clinical Research in Aging and Psychology at the
+University of Southern California.
+
+The project involves a screening part where all twins in Sweden older
+than 65 years are interviewed by telephone. Twins who meet certain
+criteria are passed on to the next stage. In this latter stage, twins who
+want to participate are visited by a doctor/nurse team. Some of the
+examinations include physical and neuropsychological examination,
+laboratory testing, neuroimaging, psychological status assessment, and family
+history collection. In addition, data are collected on medical and
+environmental risk factors.
+
+More information about Twin studies can be found at:
+
+@example
+@url{http://www.imm.ki.se/TWIN/TWINUKW.HTM}
+@end example
+
+The latter part of the project is administered with a web interface
+written using Perl and @strong{MySQL}.
+
+Each night all data from the interviews are moved into a @strong{MySQL}
+database.
+
+@menu
+* Twin pool:: Find all non-distributed twins
+* Twin event:: Show a table on twin pair status
+@end menu
+
+@node Twin pool, Twin event, Twin, Twin
+@subsection Find all non-distributed twins
+
+The following query is used to determine who goes into the second part of the
+project:
+
+@example
+select
+ concat(p1.id, p1.tvab) + 0 as tvid,
+ concat(p1.christian_name, " ", p1.surname) as Name,
+ p1.postal_code as Code,
+ p1.city as City,
+ pg.abrev as Area,
+ if(td.participation = "Aborted", "A", " ") as A,
+ p1.dead as dead1,
+ l.event as event1,
+ td.suspect as tsuspect1,
+ id.suspect as isuspect1,
+ td.severe as tsevere1,
+ id.severe as isevere1,
+ p2.dead as dead2,
+ l2.event as event2,
+ h2.nurse as nurse2,
+ h2.doctor as doctor2,
+ td2.suspect as tsuspect2,
+ id2.suspect as isuspect2,
+ td2.severe as tsevere2,
+ id2.severe as isevere2,
+ l.finish_date
+from
+ twin_project as tp
+ /* For Twin 1 */
+ left join twin_data as td on tp.id = td.id and tp.tvab = td.tvab
+ left join informant_data as id on tp.id = id.id and tp.tvab = id.tvab
+ left join harmony as h on tp.id = h.id and tp.tvab = h.tvab
+ left join lentus as l on tp.id = l.id and tp.tvab = l.tvab
+ /* For Twin 2 */
+ left join twin_data as td2 on p2.id = td2.id and p2.tvab = td2.tvab
+ left join informant_data as id2 on p2.id = id2.id and p2.tvab = id2.tvab
+ left join harmony as h2 on p2.id = h2.id and p2.tvab = h2.tvab
+ left join lentus as l2 on p2.id = l2.id and p2.tvab = l2.tvab,
+ person_data as p1,
+ person_data as p2,
+ postal_groups as pg
+where
+ /* p1 gets main twin and p2 gets his/her twin. */
+ /* ptvab is a field inverted from tvab */
+ p1.id = tp.id and p1.tvab = tp.tvab and
+ p2.id = p1.id and p2.ptvab = p1.tvab and
+ /* Just the sceening survey */
+ tp.survey_no = 5 and
+ /* Skip if partner died before 65 but allow emigration (dead=9) */
+ (p2.dead = 0 or p2.dead = 9 or
+ (p2.dead = 1 and
+ (p2.death_date = 0 or
+ (((to_days(p2.death_date) - to_days(p2.birthday)) / 365)
+ >= 65))))
+ and
+ (
+ /* Twin is suspect */
+ (td.future_contact = 'Yes' and td.suspect = 2) or
+ /* Twin is suspect - Informant is Blessed */
+ (td.future_contact = 'Yes' and td.suspect = 1 and id.suspect = 1) or
+ /* No twin - Informant is Blessed */
+ (ISNULL(td.suspect) and id.suspect = 1 and id.future_contact = 'Yes') or
+ /* Twin broken off - Informant is Blessed */
+ (td.participation = 'Aborted'
+ and id.suspect = 1 and id.future_contact = 'Yes') or
+ /* Twin broken off - No inform - Have partner */
+ (td.participation = 'Aborted' and ISNULL(id.suspect) and p2.dead = 0))
+ and
+ l.event = 'Finished'
+ /* Get at area code */
+ and substring(p1.postal_code, 1, 2) = pg.code
+ /* Not already distributed */
+ and (h.nurse is NULL or h.nurse=00 or h.doctor=00)
+ /* Has not refused or been aborted */
+ and not (h.status = 'Refused' or h.status = 'Aborted'
+ or h.status = 'Died' or h.status = 'Other')
+order by
+ tvid;
+@end example
+
+Some explanations:
+@table @asis
+@item @code{concat(p1.id, p1.tvab) + 0 as tvid}
+We want to sort on the concatenated @code{id} and @code{tvab} in
+numerical order. Adding @code{0} to the result causes @strong{MySQL} to
+treat the result as a number.
+@item column @code{id}
+This identifies a pair of twins. It is a key in all tables.
+@item column @code{tvab}
+This identifies a twin in a pair. It has a value of @code{1} or @code{2}.
+@item column @code{ptvab}
+This is an inverse of @code{tvab}. When @code{tvab} is @code{1} this is
+@code{2}, and vice versa. It exists to save typing and to make it easier for
+@strong{MySQL} to optimize the query.
+@end table
+
+This query demonstrates, among other things, how to do lookups on a
+table from the same table with a join (@code{p1} and @code{p2}). In the example, this
+is used to check whether a twin's partner died before the age of 65. If so,
+the row is not returned.
+
+All of the above exist in all tables with twin-related information. We
+have a key on both @code{id,tvab} (all tables) and @code{id,ptvab}
+(@code{person_data}) to make queries faster.
+
+On our production machine (A 200MHz UltraSPARC), this query returns
+about 150-200 rows and takes less than one second.
+
+The current number of records in the tables used above:
+@multitable @columnfractions .3 .5
+@item @strong{Table} @tab @strong{Rows}
+@item @code{person_data} @tab 71074
+@item @code{lentus} @tab 5291
+@item @code{twin_project} @tab 5286
+@item @code{twin_data} @tab 2012
+@item @code{informant_data} @tab 663
+@item @code{harmony} @tab 381
+@item @code{postal_groups} @tab 100
+@end multitable
+
+@node Twin event, , Twin pool, Twin
+@subsection Show a table on twin pair status
+
+Each interview ends with a status code called @code{event}. The query
+shown below is used to display a table over all twin pairs combined by
+event. This indicates in how many pairs both twins are finished, in how many
+pairs one twin is finished and the other refused, and so on.
+
+@example
+select
+ t1.event,
+ t2.event,
+ count(*)
+from
+ lentus as t1,
+ lentus as t2,
+ twin_project as tp
+where
+ /* We are looking at one pair at a time */
+ t1.id = tp.id
+ and t1.tvab=tp.tvab
+ and t1.id = t2.id
+ /* Just the sceening survey */
+ and tp.survey_no = 5
+ /* This makes each pair only appear once */
+ and t1.tvab='1' and t2.tvab='2'
+group by
+ t1.event, t2.event;
+
+@end example
+
+@cindex Server functions
+@node Server, Replication, Tutorial, Top
+@chapter MySQL server functions
+
+@menu
+* Languages:: What languages are supported by @strong{MySQL}?
+* Table size:: How big @strong{MySQL} tables can be
+@end menu
+
+@cindex Which languages @strong{MySQL} supports
+@cindex Language support
+@node Languages, Table size, Server, Server
+@section What languages are supported by MySQL?
+
+@code{mysqld} can issue error messages in the following languages: Czech,
+Dutch, English (the default), Estonia, French, German, Hungarian, Italian,
+Norwegian, Norwegian-ny, Polish, Portuguese, Spanish and Swedish.
+
+To start @code{mysqld} with a particular language, use either the
+@code{--language=lang} or @code{-L lang} options. For example:
+
+@example
+shell> mysqld --language=swedish
+@end example
+
+or:
+
+@example
+shell> mysqld --language=/usr/local/share/swedish
+@end example
+
+Note that all language names are specified in lowercase.
+
+The language files are located (by default) in
+@file{@var{mysql_base_dir}/share/@var{LANGUAGE}/}.
+
+To update the error message file, you should edit the @file{errmsg.txt} file
+and execute the following command to generate the @file{errmsg.sys} file:
+
+@example
+shell> comp_err errmsg.txt errmsg.sys
+@end example
+
+If you upgrade to a newer version of @strong{MySQL}, remember to repeat
+your changes with the new @file{errmsg.txt} file.
+
+@menu
+* Character sets:: The character set used for data and sorting
+* Adding character set:: Adding a new character set
+* String collating:: String collating support
+* Multi-byte characters:: Multi-byte character support
+@end menu
+
+@node Character sets, Adding character set, Languages, Languages
+@subsection The character set used for data and sorting
+
+By default, @strong{MySQL} uses the ISO-8859-1 (Latin1) character
+set. This is the character set used in the USA and western Europe.
+
+The character set determines what characters are allowed in names and how
+things are sorted by the @code{ORDER BY} and @code{GROUP BY} clauses of
+the @code{SELECT} statement.
+
+You can change the character set with the
+@code{--default-character-set} option when you start the server.
+The character sets available depend on the @code{--with-charset=charset}
+option to @code{configure}, and the character set configuration files
+listed in @file{SHAREDIR/charsets/Index}.
+@xref{Quick install}.
+
+When a client connects to a @strong{MySQL} server, the server sends the
+default character set in use to the client. The client will switch to
+use this character set for this connection.
+
+One should use @code{mysql_real_escape_string()} when escaping strings
+for a SQL query. @code{mysql_real_escape_string()} is identical to the
+old @code{mysql_escape_string()} function, except that it takes the MYSQL
+connection handle as the first parameter.
+
+If the client is compiled with different paths than where the server is
+installed and the user that configured @strong{MySQL} didn't included all
+character sets in the @strong{MySQL} binary one must specify for
+the client where it can find the additional character sets it will need
+if the server runs with a different character set than the client.
+
+On can specify this by putting in a @strong{MySQL} option file:
+
+@example
+[client]
+default-set-dir=/usr/local/mysql/share/mysql/charsets
+@end example
+
+where the path points to where the dynamic @strong{MySQL} character sets
+are stored.
+
+One can force the client to use specific character set by specifying:
+
+@example
+[client]
+default-character-set=character-set-name
+@end example
+
+but normally this is never needed.
+
+To add another character set to @strong{MySQL}, use the following procedure:
+
+@node Adding character set, String collating, Character sets, Languages
+@subsection Adding a new character set
+
+@enumerate
+@item
+Choose a name for the character set, denoted @code{MYSET} below.
+
+@item
+Decide if the set is simple or complex. If the character set
+does not need to use special string collating routines for
+sorting, and does not need mulit-byte character support, it is
+simple. If it needs either of those features, it is complex.
+
+@item
+If the character set is simple, then create the file
+@file{sql/share/charsets/MYSET.conf}, and add MYSET the
+@file{sql/share/charsets/Index} file. Read the
+@file{sql/share/charsets/README} for more instructions.
+
+@item
+Add the character set name to the @code{CHARSETS_AVAILABLE} and
+@code{COMPILED_CHARSETS} lists in @code{configure.in}.
+
+@item
+Reconfigure, recompile and test.
+
+@item
+If the character set is complex, create the file
+@file{strings/ctype-MYSET.c} in the @strong{MySQL} source distribution.
+
+@item
+Add MYSET to the end of the @file{sql/share/charsets/Index} file. Take
+note of its position in the file - this is its character set number,
+denoted @code{MYNUMBER} below.
+
+@item
+Look at one of the existing @file{ctype-*.c} files to see what needs to be
+defined. Note that the arrays in your file must have names like
+@code{ctype_MYSET}, @code{to_lower_MYSET} and so on.
+
+Near the top of the file, place a special comment like this:
+
+@example
+/*
+ * This comment is parsed by configure to create ctype.c,
+ * so don't change it unless you know what you are doing.
+ *
+ * .configure. number_MYSET=MYNUMBER
+ * .configure. strxfrm_multiply_MYSET=N
+ * .configure. mbmaxlen_MYSET=N
+ */
+@end example
+
+The @code{configure} program uses this comment to include
+the character set into the @strong{MySQL} library automatically.
+
+The strxfrm_multiply and mbmaxlen lines will be explained in
+the following sections. Only include them if you the string
+collating functions or the multi-byte character set functions,
+respectively.
+
+@code{to_lower[]} and @code{to_upper[]} are simple arrays that hold the
+lowercase and uppercase characters corresponding to each member of the
+character set. For example:
+
+@example
+to_lower['A'] should contain 'a'
+to_upper['a'] should contain 'A'
+@end example
+
+@code{sort_order[]} is a map indicating how characters should be ordered for
+comparison and sorting purposes. For many character sets, this is the same as
+@code{to_upper[]} (which means sorting will be case insensitive).
+@strong{MySQL} will sort characters based on the value of
+@code{sort_order[character]}. For more complicated sorting rules, see
+the discussion of string collating below.
+
+@code{ctype[]} is an array of bit values, with one element for one character.
+(Note that @code{to_lower[]}, @code{to_upper[]} and @code{sort_order[]}
+are indexed by character value, but @code{ctype[]} is indexed by character
+value + 1. This is an old legacy to be able to handle EOF.)
+You can find the following bitmask definitions in @file{m_ctype.h}:
+
+@example
+#define _U 01 /* Upper case */
+#define _L 02 /* Lower case */
+#define _N 04 /* Numeral (digit) */
+#define _S 010 /* Spacing character */
+#define _P 020 /* Punctuation */
+#define _C 040 /* Control character */
+#define _B 0100 /* Blank */
+#define _X 0200 /* heXadecimal digit */
+@end example
+
+The @code{ctype[]} entry for each character should be the union of the
+applicable bitmask values that describe the character.
+For example, @code{'A'} is an uppercase character (@code{_U}) as well as a
+hexadecimal digit (@code{_X}), so @code{ctype['A'+1]} should contain the value:
+@example
+_U + _X = 01 + 0200 = 0201
+@end example
+
+@item
+Add support for the string collating or multi-byte features needed, as
+described in the following sections.
+
+@item
+Add the character set name to the @code{CHARSETS_AVAILABLE} and
+@code{COMPILED_CHARSETS} lists in @code{configure.in}.
+
+@item
+Reconfigure, recompile and test.
+@end enumerate
+
+@cindex String collating
+@node String collating, Multi-byte characters, Adding character set, Languages
+@subsection String collating support
+
+If the sorting rules for your language are too complex to be handled
+with the simple @code{sort_order[]} table, you need to use the string
+collating functions.
+
+Right now the best documentation on this is the character sets that are
+already implemented. Look at the big5, czech, gbk, sjis and tis160
+character sets for examples.
+
+You must specify the @code{strxfrm_multiply_MYSET=N} value in the
+special comment at the top of the file. @code{N} should be set to
+the maximum ratio the strings may grow during my_strxfrm_MYSET (it
+must be a positive integer).
+
+@cindex Multi-byte characters
+@node Multi-byte characters, , String collating, Languages
+@subsection Multi-byte character support
+
+If your character set includes multi-byte characters, you need to use
+the multi-byte character functions.
+
+Right now the best documentation on this is the character sets that are
+already implemented. Look at the euc_kr, gb2312, gbk, sjis and ujis
+character sets for examples.
+
+You must specify the @code{mbmaxlen_MYSET=N} value in the
+special comment at the top of the file. @code{N} should be set to
+the size in bytes of the largest character in the set.
+
+@cindex Table size
+@cindex Size of tables
+@node Table size, , Languages, Server
+@section How big MySQL tables can be
+
+@strong{MySQL} 3.22 has a 4G limit on table size. With the new
+@code{MyISAM} in @strong{MySQL} 3.23 the maximum table size is pushed up
+to 8 million terabytes (2 ^ 63 bytes).
+
+Note however that operating systems have their own file size
+limits. Here are some examples:
+
+@multitable @columnfractions .6 .4
+@item Linux-Intel @tab 2G (or 4G with reiserfs)
+@item Linux-Alpha @tab 8T (?)
+@item Solaris 2.5.1 @tab 2G (possible 4G with patch)
+@item Solaris 2.6 @tab 4G
+@item Solaris 2.7 Intel @tab 4G
+@item Solaris 2.7 ULTRA-SPARC @tab 8T (?)
+@end multitable
+
+This means that the table size for @strong{MySQL} is normally limited by
+the operating system.
+
+By default, @strong{MySQL} tables have a maximum size of about 4G. You can
+check the maximum table size for a table with the @code{SHOW TABLE STATUS}
+command or with the @code{myisamchk -dv table_name}.
+@xref{SHOW}.
+
+If you need bigger tables than 4G (and your operating system supports
+this), you should set the @code{AVG_ROW_LENGTH} and @code{MAX_ROWS}
+parameter when you create your table. @xref{CREATE TABLE}. You can
+also set these later with @code{ALTER TABLE}. @xref{ALTER TABLE}.
+
+If you need to have bigger tables than 2G / 4G
+
+If your big table is going to be read-only, you could use
+@code{myisampack} to merge and compress many tables to one.
+@code{myisampack} usually compresses a table by at least 50%, so you can
+have, in effect, much bigger tables. @xref{myisampack, ,
+@code{myisampack}}.
+
+Another solution can be the included MERGE library, which allows you to
+handle a collection of identical tables as one. (Identical in this case
+means that all tables are created with identical column information.)
+Currently MERGE can only be used to scan a collection of tables because it
+doesn't support indexes. We will add indexes to this in the near future.
+
+@cindex Replication
+@node Replication, Performance, Server, Top
+@chapter Replication in MySQL
+@menu
+* Replication Intro:: Introduction
+* Replication Implementation:: Replication Implementation Overview
+* Replication HOWTO:: HOWTO
+* Replication Features:: Replication Features
+* Replication Options:: Replication Options in my.cnf
+* Replication SQL:: SQL Commands related to replication
+@end menu
+
+@node Replication Intro, Replication Implementation, Replication, Replication
+@section Introduction
+One way replication can be used both to increase robustness and
+speed. For robustness you have two systems and switch to the backup if
+you have problems with the master. The extra speed is achieved by
+sending a part of the non-updating queries to the replica server. Of
+course this only works if non-updating queries dominate, but that is the
+normal case.
+
+Starting in 3.23.15, @strong{MySQL} supports one-way replication
+internally. One server acts as the master, while the other acts as the
+slave. Note that one server could play the roles of master in one pair
+and slave in the other. The master server keeps a binary log of updates
+and an index file to binary logs to keep track of log rotation. The
+slave upon connecting informs the master where it left off sinse the
+last successfully propogated update, catches up on the updates, and then
+blocks and waits for the master to notify it of the new updates.
+
+@node Replication Implementation, Replication HOWTO, Replication Intro, Replication
+@section Replication Implementation Overview
+
+@strong{MySQL} internal replication uses the master-slave approach. One
+server is designated as the master, while the other ( or others) as
+slave(s). The master keeps a binary log of updates. The slave connects
+to the master, catches up on the missed updates, and then starts
+receiving updates immediately as they come to the master. If the
+connection is lost, the slave will reconnect. If the master goes down,
+the slave will keep trying to connect every @code{master-connect-retry}
+seconds until the master comes back up and the connection can be
+established. The slave keeps track of where it left off in the
+replication process, so it can use the info in the case it goes down and
+gets restarted later.
+
+@node Replication HOWTO, Replication Features, Replication Implementation, Replication
+@section HOWTO
+Below is a quick HOWTO on how to set up replication on your current system:
+
+@itemize @bullet
+@item
+Upgrade both slave and master to 3.23.15 or higher. We recommend that
+you use the latest 3.23 version on both the slave and the master. While
+3.23 is in beta, the versions may be not backwards compatible. In
+addition, the newer version will fix some bugs and add new features.
+@item
+Set up special replication user(s) on the master with the @code{FILE}
+privilege and permission to connect from all the slaves. If the user is
+only doing replication, you don't need to grant him other privileges.
+@item
+Take a snapshot of all the tables/databases on the master that could
+possibly be involved in the update queries before taking the next step
+@item
+In @code{my.cnf} on the master add @code{log-bin} and restart it. Make
+sure there are no important updates to the master between the time you
+have taken the snapshot and the time master is restarted with
+@code{log-bin} option
+@item
+Load the snapshot of the master to all the slaves
+@item
+Add the following to @code{my.cnf} on the slave(s):
+
+@example
+master-host=<hostname of the master>
+master-user=<replication user name>
+master-password=<replication user password>
+@end example
+
+replacting the values in <> with what is relevant to your system.
+
+@item Restart the slave(s)
+
+@end itemize
+
+After you have done the above, the master and the slave(s) should be in
+sync.
+
+@node Replication Features, Replication Options, Replication HOWTO, Replication
+@section Replication Features
+
+Below is an explanation of what is supported and what is not:
+
+@itemize @bullet
+@item
+Replication will be done correctly with @code{AUTO_INCREMENT},
+@code{LAST_INSERT_ID}, and @code{TIMESTAMP} values
+@item
+@code{LOAD DATA INFILE} will be handled properly as long as the file
+still resides on the master server at the time of update
+propogation. @code{LOAD LOCAL DATA INFILE} will be skipped.
+@item
+Update queries that use user variables are not replication-safe (yet)
+@item
+If the query on the slave gets an error, the slave thread will
+terminate, and a message will appear in @code{.err} file. You should
+then connect to the slave manually, fix the cause of the error
+(eg. non-existent table), and then run @code{SLAVE START} sql command (
+available starting in 3.23.16, in 3.23.15 you will have to restart the
+server).
+@item
+If connection to the master is lost, the slave will retry immediately,
+and then in case of failure every @code{master-connect-retry} (default
+60) seconds. Because of this, it is safe to shut down the master, and
+then restart it after a while. The slave will also be able to deal with
+network connectivity outages.
+@item
+Shutting down the slave (cleanly) is also safe, as it keeps track of
+where it left off. Unclean shutdowns might produce problems, especially
+if disk cache was not synced before the system died. Your system fault
+tolerance will be greatly increased if you have a good UPS.
+@item
+If the master is listening on a non-standard port, you will also need to
+specify this with @code{master-port} parameter in @code{my.cnf} .
+@item
+In 3.23.15,all of the tables and databases will be replicated. Starting
+in 3.23.16, you can restrict replication to a set of databases with
+@code{replicate-do-db} directives in @code{my.cnf} or just excluse a set
+of databases with @code{replicate-ignore-db}.
+@item
+Starting in 3.23.16, @code{SET SQL_LOG_BIN = 0} will turn off
+replication (binary) logging on the master, and @code{SET SQL_LOG_BIN =
+1} will turn in back on - you must have the process privilege to do
+this.
+@item
+The slave thread does not log updates to the binary log of the slave,
+so it is possible to couple two servers in a mutual master-slave
+relationship. You can actually set up a load balancing scheme and do
+queries safely on either of the servers. Just do not expect to do LOCK
+TABLES on one server, then connect to the other and still have that
+lock :-) .
+@item
+Starting in 3.23.19 you can clean up stale replication leftovers when
+something goes wrong and you want a clean start with @code{FLUSH MASTER}
+and @code{FLUSH SLAVE} commands
+@item
+Starting in 3.23.21 you can use LOAD TABLE FROM MASTER for network
+backup and to set up replication initially.
+@end itemize
+
+@node Replication Options, Replication SQL, Replication Features, Replication
+@section Replication Options in my.cnf
+
+The table below explains the replications options in @code{my.cnf} . All
+of the are available starting in 3.23.15 unless indicated otherwise.
+
+@multitable @columnfractions .25 .25 .25 .25
+@item @strong{Option} @tab @strong{Description} @tab @strong{Where to set} @tab @strong{Example}
+@item @code{log-bin} @tab Should be set on the master. Tells it to keep a binary update
+log. If a parameter is specified, the log will be written to the specified location. @tab Master @tab
+@code{log-bin}
+@item @code{log-bin-index} @tab Because the user could issue @code{FLUSH LOGS} command, we need to
+know which log is currently active and which ones have been rotated out and it what sequence. This info
+is stored in the binary log index file. The default is `hostname`.index . You can use this option
+if you want to be a rebel. @tab Master @tab @code{log-bin-index=db.index}
+@item @code{master-host} @tab Master hostname or IP address for replication. If not set,
+the slave thread will not be started @tab Slave @tab @code{master-host=db-master.mycompany.com}
+@item @code{master-user} @tab The user the slave thread will authenticate as when connecting to
+the master. The user must have @code{FILE} privilige. If the master user is not set, user @code{test}
+ is assumed. @tab Slave @tab @code{master-user=scott}
+@item @code{master-password} @tab The password the slave thread will authenticate with when
+connecting to the master. If not set, empty password is assumed @tab Slave @tab
+@code{master-password=tiger}
+@item @code{master-port} @tab The port the master is listening on. If not set, the compiled setting of
+@code{MYSQL_PORT} is assumed. If you have not tinkered with @code{configure} options, this should be
+3306. @tab Slave @tab @code{master-port=3306}
+@item @code{master-connect-retry} @tab The number of seconds the slave thread will sleep before retrying
+to connect to the master in case the master goes down or the connection is lost.
+Default is 60. @tab Slave @tab @code{master-connect-retry=60}
+@item @code{master-info-file} @tab
+The location of the file that remembers where we left off on the master
+during the replication process. The default is master.info in the data
+directory. Sasha: The only reason I see for ever changing the default
+is the desire to be rebelious.
+@tab Slave @tab @code{master-info-file=master.info}
+@item @code{replicate-do-db} @tab Tells the slave thread to restrict replication to the specified database. To specify more than one database, use the directive multiple times, once for each database.
+Note that this will only work if you do not use cross-database queries such as
+@code{UPDATE some_db.some_table SET foo='bar'} while having selected a different or
+no database. @tab Slave @tab @code{replicate-do-db=some_db}
+@item @code{replicate-ignore-db} @tab Tells the slave thread to not replicate to the specified
+database. To specify more than one database to ignore, use the directive multiple times,
+once for each database. You must not use cross database updates for this option. @tab Slave @tab @code{replicate-ignore-db=some_db}
+@item @code{sql-bin-update-same} @tab If set, setting @code{SQL_LOG_BIN} to a value will
+automatically set @code{SQL_LOG_UPDATE} to the same value and vice
+versa. @tab Master @tab @code{sql-bin-update-same}
+
+@item @code{log-slave-updates} @tab Tells the slave to log the updates from the slave thread to the binary log. Off by default. You will need to turn it on if you plan to daisy-chain the slaves @tab Slave @tab @code{log-slave-updates}
+
+@end multitable
+
+@node Replication SQL, , Replication Options, Replication
+@section SQL commands related to replication
+
+Replication can be controlled through the SQL interface. Below is the
+summary of commands:
+
+@multitable @columnfractions .30 .40 .30
+@item @strong{Command} @tab @strong{Description} @tab @strong{Where to run}
+@item @code{SLAVE START} @tab Starts the slave thread. @tab Slave
+@item @code{SLAVE STOP} @tab Stops the slave thread. @tab Slave
+@item @code{SET SQL_LOG_BIN=0} @tab Disables update logging @tab Master
+@item @code{SET SQL_LOG_BIN=1} @tab Re-enable update logging @tab Master
+@item @code{FLUSH MASTER} @tab Deletes all binary logs listed in the inded file, resetting the binlog index file to be empty. @tab Master
+@item @code{FLUSH SLAVE} @tab Makes the slave forget its replication position in the master logs @tab Slave
+@item @code{LOAD TABLE tblname FROM MASTER} @tab Downloads a copy of the table from master to the slave @tab Slave
+@end multitable
+
+@cindex Performance
+@cindex Optimization
+@node Performance, MySQL Benchmarks, Replication, Top
+@chapter Getting maximum performance from MySQL
+
+Optimization is a complicated task because it ultimately requires
+understanding of the whole system. While it may be possible to do some
+local optimizations with small knowledge of your system/application, the
+more optimal you want your system to become the more you will have to
+know about it.
+
+So this chapter will try to explain and give some examples of different
+ways to optimize @strong{MySQL}. But remember that there are always some
+(increasingly harder) ways to make the system even faster left to do.
+
+@menu
+* Optimize Basics:: Optimization overview
+* System:: System/Compile time and startup parameter tuning
+* Data size:: Get your data as small as possible
+* MySQL indexes:: How @strong{MySQL} uses indexes
+* Query Speed:: Speed of queries that access or update data
+* Tips:: Other optimization tips
+* Benchmarks:: Using your own benchmarks
+* Design:: Design choices
+* Design Limitations:: MySQL design limitations/tradeoffs
+* Portability:: Portability
+* Internal use:: What have we used MySQL for?
+@end menu
+
+@node Optimize Basics, System, Performance, Performance
+@section Optimization overview
+
+The most important part for getting a system fast is of course the basic
+design. You also need to know what kinds of things your system will be
+doing, and what your bottlenecks are.
+
+The most common bottlenecks are:
+@itemize @bullet
+@item Disk seeks
+It takes time for the disk to find a piece of data. With modern disks in
+1999 the mean time for this is usually lower than 10ms, so we can in
+theory do about 1000 seeks a second. This time improves slowly with new
+disks and is very hard to optimize for a single table. The way to
+optimize this is to spread the data on more than one disk.
+@item Disk reading/writing
+When the disk is at the correct position we need to read the data. With
+modern disks in 1999 one disk delivers something like 10-20Mb/s. This
+is easier to optimize than seeks because you can read in parallel from
+multiple disks.
+@item CPU cycles
+When we have got the data into main memory (or if it already were
+there) we need to process it to get to our result. When we have small
+tables compared to the memory this is the most common limiting
+factor. But then with small tables speed is usually not the problem.
+@item Memory bandwidth
+When the CPU needs more data than can fit in the CPU cache the main
+memory bandwidth becomes a bottleneck. This is an uncommon bottleneck
+for most systems but one should be aware of it.
+@end itemize
+
+@node System, Data size, Optimize Basics, Performance
+@section System/Compile time and startup parameter tuning
+
+We start with the system level things since some of these decisions have
+to be made very early. In other cases a fast look at this part may
+suffice because it not that important for the big gains. However, it is always
+nice to have a feeling about how much one could gain by changing things
+at this level.
+
+The default OS to use is really important! To get the most use of
+multiple CPU machines one should use Solaris (because the threads works
+really nice) or Linux (because the 2.2 kernel has really good SMP
+support). Also on 32bit machines Linux has a 2G file size limit by
+default. Hopefully this will be fixed soon when new filesystems is
+released (XFS/Reiserfs).
+
+Because we have not run @strong{MySQL} in production on that many platforms we
+advice you to test your intended platform before choosing it, if possible.
+
+Other tips:
+@itemize @bullet
+@item
+If you have enough RAM, you could remove all swap devices. Some
+operating systems will use a swap device in some contexts even if you
+have free memory.
+@item
+Use the @code{--skip-locking} @strong{MySQL} option to avoid external
+locking. Note that this will not impact @strong{MySQL}'s functionality as
+long as you only run one server. Just remember to take down the server (or
+lock relevant parts) before you run @code{myisamchk}. On some system
+this switch is mandatory because the external locking does not work in any
+case.
+
+The @code{--skip-locking} option is on by default when compiling with
+MIT-pthreads, because @code{flock()} isn't fully supported by
+MIT-pthreads on all platforms.
+
+The only case when you can't use @code{--skip-locking} is if you run
+multiple @strong{MySQL} @emph{servers} (not clients) on the same data, or run
+@code{myisamchk} on the table without first flushing and locking the
+@code{mysqld} server tables first.
+
+You can still use @code{LOCK TABLES} / @code{UNLOCK TABLES} even if you
+are using @code{--skip-locking}
+@end itemize
+
+@menu
+* Compile and link options:: How compiling and linking affects the speed of MySQL
+* Disk issues:: Disk issues
+* Server parameters:: Tuning server parameters
+* Table cache:: How MySQL opens and closes tables
+* Creating many tables:: Drawbacks of creating large numbers of tables in the same database
+* Open tables:: Why so many open tables?
+* Memory use:: How MySQL uses memory
+* Internal locking:: How MySQL locks tables
+* Table locking:: Table locking issues
+@end menu
+
+@node Compile and link options, Disk issues, System, System
+@subsection How compiling and linking affects the speed of MySQL
+
+Most of the following tests are done on Linux with the
+@strong{MySQL} benchmarks, but they should give some indication for
+other operating systems and workloads.
+
+You get the fastest executable when you link with @code{-static}.
+
+On Linux, you will get the fastest code when compiling with @code{pgcc}
+and @code{-O6}. To compile @file{sql_yacc.cc} with these options, you
+need about 200M memory because @code{gcc/pgcc} needs a lot of memory to
+make all functions inline. You should also set @code{CXX=gcc} when
+configuring @strong{MySQL} to avoid inclusion of the @code{libstdc++}
+library (it is not needed). Note that with some versions of @code{pgcc},
+the resulting code will only run on true Pentium processors, even if you
+use the compiler option that you want the resulting code to be working on
+all x586 type processors (Like AMD).
+
+By just using a better compiler and/or better compiler options you can
+get a 10-30 % speed increase in your application. This is particularly
+important if you compile the SQL server yourself!
+
+We have tested the both Cygnus CodeFusion and the Fujitsu compiler but
+when we tested them, neither was enough bug free enough to compile
+@strong{MySQL} with optimizations on.
+
+When you compile @strong{MySQL} you should only include support for the
+character sets that you are going to use. (Option @code{--with-charset=xxx}).
+The standard @strong{MySQL} binary distributions are compiled with support
+for all character sets.
+
+Here is a list of some mesurements that we have done:
+@itemize @bullet
+@item
+If you use @code{pgcc} and compile everything with @code{-O6}, the
+@code{mysqld} server is 11% faster than with @code{gcc} versions
+older than @code{gcc} 2.95.2.
+
+@item
+If you link dynamically (without @code{-static}), the result is 13%
+slower. Note that you still can use a dynamic linked @strong{MySQL}
+library. It is only the server that is critical for performance.
+
+@item
+If you connect using TCP/IP rather than Unix sockets, the result is 7.5%
+slower on the same computer. (If you are connection to @code{localhost},
+@strong{MySQL} will by default use sockets).
+
+@item
+On a Sun SPARCstation 10, @code{gcc} 2.7.3 is 13% faster than Sun Pro C++ 4.2.
+
+@item
+On Solaris 2.5.1, MIT-pthreads is 8-12% slower than Solaris native
+threads on a single processor. With more load/CPUs the difference should
+get bigger.
+@end itemize
+
+The @strong{MySQL}-Linux distribution provided by MySQL AB used to be
+compiled with @code{pgcc}, but we had to go back to regular gcc because
+of a bug in @code{pgcc} that would generate the code that does not run
+on AMD. We will continue using gcc until that bug is resolved. In the
+meantime, if you have a non-AMD machine, you can get a faster binary by
+compiling with @code{pgcc}. The standard MySqL Linux binary is linked
+statically to get it faster and more portable.
+
+
+@node Disk issues, Server parameters, Compile and link options, System
+@subsection Disk issues
+
+@itemize @bullet
+@item
+As mentioned before disks seeks are a big performance bottleneck. This
+problems gets more and more apparent when the data starts to grow so
+large that effective caching becomes impossible. For large databases,
+where you access data more or less randomly, you can be sure that you
+will need at least one disk seek to read and a couple of disk seeks to
+write things. To minimize this problem, use disks with low seek times.
+@item
+Increase the number of available disk spindles (and thereby reduce
+the seek overhead) by either symlink files to different disks or stripe
+the disks.
+@table @strong
+@item Using symbolic links
+This means that you symlink the index and/or data file(s) from the
+normal data directory to another disk (that may also be striped). This
+makes both the seek and read times better (if the disks are not used for
+other things). @xref{Symbolic links}.
+@item Striping
+Striping means that you have many disks and put the first block on the
+first disk, the second block on the second disk, and the Nth on the (Nth
+mod number_of_disks) disk, and so on. This means if your normal data
+size is less than the stripe size (or perfectly aligned) you will get
+much better performance. Note that striping if very dependent on the OS
+and stripe-size. So benchmark your application with different
+stripe-sizes. @xref{Benchmarks}.
+
+Note that the speed difference for striping is @strong{very} dependent
+on the parameters. Depending on how you set the striping parameters and
+number of disks you may get difference in orders of magnitude. Note that
+you have to choose to optimize for random or sequential access.
+@end table
+@item
+For reliability you may want to use RAID 0+1 (striping + mirroring), but
+in this case you will need 2*N drives to hold N drives of data. This is
+probably the best option if you have the money for it! You may however
+also have to invest in some volume management software to handle it
+efficiently.
+@item
+A good option is to have semi-important data (that can be re-generated)
+on RAID 0 disk while store really important data (like host information
+and logs) on a RAID 0+1 or RAID N disks. RAID N can be a problem if you
+have many writes because of the time to update the parity bits.
+@item
+You may also set the parameters for the file system that the database
+uses. One easy change is to mount the file system with the noatime
+option. That makes it skip the updating of the last access time in the
+inode and by this will avoid some disk seeks.
+@item
+On Linux, you can get much more performance (up to 100 % under load is
+not uncommon) by using hdpram to configure your disks interface! The
+following should be quite good hdparm options for @code{MySQL} (and
+probably many other applications):
+@example
+hdparm -m 16 -d 1
+
+@end example
+
+Note that the performance/reliability when using the above depends on
+your hardware, so we strongly suggest that you test your system
+throughly after using @code{hdparm}! Please consult the @code{hdparm}
+man page for more information! If @code{hdparm} is not used wisely,
+filesystem corruption may result. Backup everything before experimenting!
+@item
+On many OS system you can mount the disks with the 'async' flag to set the file
+system to be updated asynchronously. If your computer is reasonable stable,
+this should give you more performance without sacrificing too much reliability.
+(This flag is on by default on Linux).
+@item
+If you don't need to know when a file was last accessed (which is not
+really useful on a databasa server), you can mount your file systems
+with the noatime flag.
+@end itemize
+
+@menu
+* Symbolic links:: Using symbolic links for databases and tables
+@end menu
+
+@node Symbolic links, , Disk issues, Disk issues
+@subsubsection Using symbolic links for databases and tables
+
+You can move tables and databases from the database directory to other
+locations and replace them with symbolic links to the new locations.
+You might want to do this, for example, to move a database to a file
+system with more free space.
+
+If @strong{MySQL} notices that a table is a symbolically-linked, it will
+resolve the symlink and use the table it points to instead. This works
+on all systems that support the @code{realpath()} call (at least Linux
+and Solaris support @code{realpath()})! On systems that don't support
+@code{realpath()}, you should not access the table through the real path
+and through the symlink at the same time! If you do, the table will be
+inconsistent after any update.
+
+@strong{MySQL} doesn't that you link one directory to multiple
+databases. Replacing a database directory with a symbolic link will
+work fine as long as you don't make a symbolic link between databases.
+Suppose you have a database @code{db1} under the @strong{MySQL} data
+directory, and then make a symlink @code{db2} that points to @code{db1}:
+
+@example
+shell> cd /path/to/datadir
+shell> ln -s db1 db2
+@end example
+
+Now, for any table @code{tbl_a} in @code{db1}, there also appears to be
+a table @code{tbl_a} in @code{db2}. If one thread updates @code{db1.tbl_a}
+and another thread updates @code{db2.tbl_a}, there will be problems.
+
+If you really need this, you must change the following code in
+@file{mysys/mf_format.c}:
+
+@example
+if (flag & 32 || (!lstat(to,&stat_buff) && S_ISLNK(stat_buff.st_mode)))
+@end example
+
+to
+
+@example
+if (1)
+@end example
+
+On windows you can use internal symbolic links to directories by compiling
+@strong{MySQL} with @code{-DUSE_SYMDIR}. This allows you to put different
+databases on different disks. @xref{Win32 symbolic links}.
+
+@cindex Startup parameters
+@node Server parameters, Table cache, Disk issues, System
+@subsection Tuning server parameters
+
+You can get the default buffer sizes used by the @code{mysqld} server
+with this command:
+
+@example
+shell> mysqld --help
+@end example
+
+This command produces a list of all @code{mysqld} options and configurable
+variables. The output includes the default values and looks something
+like this:
+
+@example
+Possible variables for option --set-variable (-O) are:
+back_log current value: 5
+bdb_cache_size current value: 1048540
+connect_timeout current value: 5
+delayed_insert_timeout current value: 300
+delayed_insert_limit current value: 100
+delayed_queue_size current value: 1000
+flush_time current value: 0
+interactive_timeout current value: 28800
+join_buffer_size current value: 131072
+key_buffer_size current value: 1048540
+lower_case_table_names current value: 0
+long_query_time current value: 10
+max_allowed_packet current value: 1048576
+max_connections current value: 100
+max_connect_errors current value: 10
+max_delayed_threads current value: 20
+max_heap_table_size current value: 16777216
+max_join_size current value: 4294967295
+max_sort_length current value: 1024
+max_tmp_tables current value: 32
+max_write_lock_count current value: 4294967295
+myisam_sort_buffer_size current value: 8388608
+net_buffer_length current value: 16384
+net_retry_count current value: 10
+net_read_timeout current value: 30
+net_write_timeout current value: 60
+query_buffer_size current value: 0
+record_buffer current value: 131072
+slow_launch_time current value: 2
+sort_buffer current value: 2097116
+table_cache current value: 64
+thread_concurrency current value: 10
+tmp_table_size current value: 1048576
+thread_stack current value: 131072
+wait_timeout current value: 28800
+@end example
+
+If there is a @code{mysqld} server currently running, you can see what
+values it actually is using for the variables by executing this command:
+
+@example
+shell> mysqladmin variables
+@end example
+<<<<<<< manual.texi
+
+Each option is described below. Values for buffer sizes, lengths and stack
+sizes are given in bytes. You can specify values with a suffix of @samp{K}
+or @samp{M} to indicate kilobytes or megabytes. For example, @code{16M}
+indicates 16 megabytes. The case of suffix letters does not matter;
+@code{16M} and @code{16m} are equivalent.
+
+You can also see some statistics from a running server by issuing the command
+@code{SHOW STATUS}. @xref{SHOW}.
+
+@table @code
+@item @code{ansi_mode}.
+Is @code{ON} if @code{mysqld} was started with @code{--ansi}.
+@xref{Ansi mode}.
+
+@item @code{back_log}
+The number of outstanding connection requests @strong{MySQL} can have. This
+comes into play when the main @strong{MySQL} thread gets @strong{VERY}
+many connection requests in a very short time. It then takes some time
+(although very little) for the main thread to check the connection and start
+a new thread. The @code{back_log} value indicates how many requests can be
+stacked during this short time before @strong{MySQL} momentarily stops
+answering new requests. You need to increase this only if you expect a large
+number of connections in a short period of time.
+
+In other words, this value is the size of the listen queue for incoming
+TCP/IP connections. Your operating system has its own limit on the size
+of this queue. The manual page for the Unix @code{listen(2)} system
+call should have more details. Check your OS documentation for the
+maximum value for this variable. Attempting to set @code{back_log}
+higher than your operating system limit will be ineffective.
+
+@item @code{bdb_cache_size}
+The buffer that is allocated to cache index and rows for @code{BDB} tables.
+If you don't use @code{BDB} tables, you should set this to 0 or
+start @code{mysqld} with @code{--skip-bdb} o not waste memory for this cache.
+
+@item @code{concurrent_inserts}
+If @code{ON} (the default), @code{MySQL} will allow you to use @code{INSERT}
+on @code{MyISAM} tables at the same time as you run @code{SELECT} queries
+on them. You can turn this option off by starting mysqld with @code{--safe}
+or @code{--skip-new}.
+
+@item @code{connect_timeout}
+The number of seconds the @code{mysqld} server is waiting for a connect
+packet before responding with @code{Bad handshake}.
+
+@item @code{delayed_insert_timeout}
+How long a @code{INSERT DELAYED} thread should wait for @code{INSERT}
+statements before terminating.
+
+@item @code{delayed_insert_limit}
+After inserting @code{delayed_insert_limit} rows, the @code{INSERT
+DELAYED} handler will check if there are any @code{SELECT} statements
+pending. If so, it allows these to execute before continuing.
+
+@item @code{delay_key_write}
+If enabled (is on by default), @strong{MySQL} will honor the
+@code{delay_key_write} option @code{CREATE TABLE}. This means that the
+key buffer for tables with this option will not get flushed on every
+index update, but only when a table is closed. This will speed up
+writes on keys a lot but you should add automatic checking of all tables
+with @code{myisamchk --fast --force} if you use this. Note that if you
+start @code{mysqld} with the @code{--delay-key-write-for-all-tables}
+option this means that all tables will be treated as if they were
+created with the @code{delay_key_write} option. You can clear this flag
+by starting @code{mysqld} with @code{--skip-new} or @code{--safe-mode}.
+
+@item @code{delayed_queue_size}
+What size queue (in rows) should be allocated for handling @code{INSERT
+DELAYED}. If the queue becomes full, any client that does @code{INSERT
+DELAYED} will wait until there is room in the queue again.
+
+@item @code{flush_time}
+If this is set to a non-zero value, then every @code{flush_time} seconds all
+tables will be closed (to free up resources and sync things to disk).
+
+@item @code{init_file}
+The name of the file specified with the @code{--init-file} option when
+you start the server. This is a file of SQL statements you want the
+server to execute when it starts.
+
+@item @code{interactive_timeout}
+The number of seconds the server waits for activity on an interactive
+connection before closing it. An interactive client is defined as a
+client that uses the @code{CLIENT_INTERACTIVE} option to
+@code{mysql_real_connect()}. See also @code{wait_timeout}.
+
+@item @code{join_buffer_size}
+The size of the buffer that is used for full joins (joins that do not
+use indexes). The buffer is allocated one time for each full join
+between two tables. Increase this value to get a faster full join when
+adding indexes is not possible. (Normally the best way to get fast joins
+is to add indexes.)
+
+@c Make texi2html support index @anchor{Index cache size}. Then change
+@c some xrefs to point here
+@item @code{key_buffer_size}
+Index blocks are buffered and are shared by all threads.
+@code{key_buffer_size} is the size of the buffer used for index blocks.
+
+Increase this to get better index handling (for all reads and multiple
+writes) to as much as you can afford; 64M on a 256M machine that mainly
+runs @strong{MySQL} is quite common. If you however make this too big
+(more than 50% of your total memory?) your system may start to page
+and become REALLY slow. Remember that because @strong{MySQL} does not cache data
+read, that you will have to leave some room for the OS filesystem cache.
+
+You can check the performance of the key buffer by doing @code{show
+status} and examine the variables @code{Key_read_requests},
+@code{Key_reads}, @code{Key_write_requests} and @code{Key_writes}. The
+@code{Key_reads/Key_read_request} ratio should normally be < 0.01.
+The @code{Key_write/Key_write_requests} is usually near 1 if you are
+using mostly updates/deletes but may be much smaller if you tend to
+do updates that affect many at the same time or if you are
+using @code{delay_key_write}. @xref{SHOW}.
+
+To get even more speed when writing many rows at the same time use
+@code{LOCK TABLES}. @xref{LOCK TABLES, , @code{LOCK TABLES}}.
+
+@item @code{lower_case_table_names}
+Change all table names to lower case on disk.
+
+@item @code{long_query_time}
+If a query takes longer than this (in seconds), the @code{Slow_queries} counter
+will be incremented.
+
+@item @code{max_allowed_packet}
+The maximum size of one packet. The message buffer is initialized to
+@code{net_buffer_length} bytes, but can grow up to @code{max_allowed_packet}
+bytes when needed. This value by default is small, to catch big (possibly
+wrong) packets. You must increase this value if you are using big
+@code{BLOB} columns. It should be as big as the biggest @code{BLOB} you want
+to use.
+
+@item @code{max_connections}
+The number of simultaneous clients allowed. Increasing this value increases
+the number of file descriptors that @code{mysqld} requires. See below for
+comments on file descriptor limits. @xref{Too many connections}.
+
+@item @code{max_connect_errors}
+If there is more than this number of interrupted connections from a host
+this host will be blocked from further connections. You can unblock a host
+with the command @code{FLUSH HOSTS}.
+
+@item @code{max_delayed_threads}
+Don't start more than this number of threads to handle @code{INSERT DELAYED}
+statements. If you try to insert data into a new table after all @code{INSERT
+DELAYED} threads are in use, the row will be inserted as if the
+@code{DELAYED} attribute wasn't specified.
+
+@item @code{max_join_size}
+Joins that are probably going to read more than @code{max_join_size}
+records return an error. Set this value if your users tend to perform joins
+without a @code{WHERE} clause that take a long time and return
+millions of rows.
+
+@item @code{max_heap_table_size}
+Don't allow creation of heap tables bigger than this.
+
+@item @code{max_sort_length}
+The number of bytes to use when sorting @code{BLOB} or @code{TEXT}
+values (only the first @code{max_sort_length} bytes of each value
+are used; the rest are ignored).
+
+@item @code{max_tmp_tables}
+(This option doesn't yet do anything).
+Maximum number of temporary tables a client can keep open at the same time.
+
+@item @code{max_write_lock_count}
+After this many write locks, allow some read locks to run in between.
+
+@item @code{myisam_sort_buffer_size}
+The buffer that is allocated when sorting the index when doing a @code{REPAIR}
+table.
+
+@item @code{net_buffer_length}
+The communication buffer is reset to this size between queries. This
+should not normally be changed, but if you have very little memory, you
+can set it to the expected size of a query. (That is, the expected length of
+SQL statements sent by clients. If statements exceed this length, the buffer
+is automatically enlarged, up to @code{max_allowed_packet} bytes.)
+
+@item @code{net_retry_count}
+If a read on a communication port is interrupted, retry this many times
+before giving up. This value should be quite high on @code{FreeBSD} as
+internal interrupts is sent to all threads.
+
+@item @code{net_read_timeout}
+Number of seconds to wait for more data from a connection before aborting
+the read. Note that when we don't expect data from a connection, the timeout
+is defined by @code{write_timeout}.
+
+@item @code{net_write_timeout}
+Number of seconds to wait for a block to be written to a connection before
+aborting the write.
+=======
+>>>>>>> 1.148
+
+<<<<<<< manual.texi
+@item @code{record_buffer}
+Each thread that does a sequential scan allocates a buffer of this
+size for each table it scans. If you do many sequential scans, you may
+want to increase this value.
+=======
+or the @code{SHOW VARIABLES} in the @code{mysql} command client.
+>>>>>>> 1.148
+
+<<<<<<< manual.texi
+@item @code{query_buffer_size}
+The initial allocation of the query buffer. If most of your queries are
+long (like when inserting blobs), you should increase this!
+=======
+You can find a full description for all variables in the @code{SHOW VARIABLES}
+section in this manual. @xref{SHOW VARIABLES}.
+>>>>>>> 1.148
+
+<<<<<<< manual.texi
+@item @code{skip_show_databases}
+This prevents people from doing @code{SHOW DATABASES}, if they don't
+have the @code{PROCESS_PRIV} privilege. This can improve security if
+you're concerned about people being able to see what databases and
+tables other users have.
+
+@item @code{slow_launch_time}
+If the creating of the thread longer than this (in seconds), the
+@code{Slow_launch_threads} counter will be incremented.
+
+@item @code{sort_buffer}
+Each thread that needs to do a sort allocates a buffer of this
+size. Increase this value for faster @code{ORDER BY} or @code{GROUP BY}
+operations.
+@xref{Temporary files}.
+
+@item @code{table_cache}
+The number of open tables for all threads. Increasing this value
+increases the number of file descriptors that @code{mysqld} requires.
+@strong{MySQL} needs two file descriptors for each unique open table.
+See below for comments on file descriptor limits. You can check if you
+need to increase the table cache by checking the @code{Opened_tables}
+variable. @xref{SHOW}. If this variable is big and you don't do
+@code{FLUSH TABLES} a lot (which just forces all tables to be closed and
+reopenend), then you should increase the value of this variable.
+
+For information about how the table cache works, see @ref{Table cache}.
+
+@item @code{thread_cache_size}
+How many threads we should keep keep in a cache for reuse. When a
+client disconnects the clients threads is put in the cache if there
+isn't more than @code{thread_cache_size} threads from before. All new
+threads are first taken from the cache and only when the cache is empty
+a new thread is created. This variable can be increased to improve
+performance if you have a lot of new connections (Normally this doesn't
+however give a notable performance improvement if you have a good
+thread implementation).
+
+@item @code{thread_concurrency}
+On Solaris, @code{mysqld} will call @code{thr_setconcurrency()} with
+this value. @code{thr_setconcurrency()} permits the application to give
+the threads system a hint, for the desired number of threads that should
+be run at the same time.
+
+@item @code{thread_stack}
+The stack size for each thread. Many of the limits detected by the
+@code{crash-me} test are dependent on this value. The default is
+large enough for normal operation. @xref{Benchmarks}.
+
+@item @code{tmp_table_size}
+If an in-memory temporary table exceeds this size, @strong{MySQL}
+will automatically convert it to an on-disk @code{MyISAM} table.
+Increase the value of @code{tmp_table_size} if you do many advanced
+@code{GROUP BY} queries and you have lots of memory.
+
+@item @code{wait_timeout}
+The number of seconds the server waits for activity on a connection before
+closing it. See also @code{interactive_timeout}.
+@end table
+=======
+You can also see some statistics from a running server by issuing the command
+@code{SHOW STATUS}. @xref{SHOW STATUS}.
+>>>>>>> 1.148
+
+@strong{MySQL} uses algorithms that are very scalable, so you can usually
+run with very little memory. If you however give @strong{MySQL} more
+memory you will normally also get better performance.
+
+When tuning a @strong{MySQL} server, the two most important variables to use
+are @code{key_buffer_size} and @code{table_cache}. You should first feel
+confident that you have these right before trying to change any of the
+other variables.
+
+If you have much memory (>=256M) and many tables and want maximum performance
+with a moderate number of clients, you should use something like this:
+
+@example
+shell> safe_mysqld -O key_buffer=64M -O table_cache=256 \
+ -O sort_buffer=4M -O record_buffer=1M &
+@end example
+
+If you have only 128M and only a few tables, but you still do a lot of
+sorting, you can use something like:
+
+@example
+shell> safe_mysqld -O key_buffer=16M -O sort_buffer=1M
+@end example
+
+If you have little memory and lots of connections, use something like this:
+
+@example
+shell> safe_mysqld -O key_buffer=512k -O sort_buffer=100k \
+ -O record_buffer=100k &
+@end example
+
+or even:
+
+@example
+shell> safe_mysqld -O key_buffer=512k -O sort_buffer=16k \
+ -O table_cache=32 -O record_buffer=8k -O net_buffer=1K &
+@end example
+
+When you have installed @strong{MySQL}, the @file{Docs} directory will
+contain some different @code{my.cnf} example files, @file{my-huge.cnf},
+@file{my-large.cnf},@file{my-medium.cnf} and@file{my-small.cnf}, you can
+use as a base to optimize your system.
+
+If there are very many connections, ``swapping problems'' may occur unless
+@code{mysqld} has been configured to use very little memory for each
+connection. @code{mysqld} performs better if you have enough memory for all
+connections, of course.
+
+Note that if you change an option to @code{mysqld}, it remains in effect only
+for that instance of the server.
+
+To see the effects of a parameter change, do something like this:
+
+@example
+shell> mysqld -O key_buffer=32m --help
+@end example
+
+Make sure that the @code{--help} option is last; otherwise, the effect of any
+options listed after it on the command line will not be reflected in the
+output.
+
+@cindex Table cache
+@findex table_cache
+@node Table cache, Creating many tables, Server parameters, System
+@subsection How MySQL opens and closes tables
+
+@code{table_cache}, @code{max_connections} and @code{max_tmp_tables}
+affect the maximum number of files the server keeps open. If you
+increase one or both of these values, you may run up against a limit
+imposed by your operating system on the per-process number of open file
+descriptors. However, you can increase the limit on many systems.
+Consult your OS documentation to find out how to do this, because the
+method for changing the limit varies widely from system to system.
+
+@code{table_cache} is related to @code{max_connections}. For example,
+for 200 concurrent running connections, you should have a table cache of
+at least @code{200 * n}, where @code{n} is the maximum number of tables
+in a join.
+
+The cache of open tables can grow to a maximum of @code{table_cache}
+(default 64; this can be changed with with the @code{-O table_cache=#}
+option to @code{mysqld}). A table is never closed, except when the
+cache is full and another thread tries to open a table or if you use
+@code{mysqladmin refresh} or @code{mysqladmin flush-tables}.
+
+When the table cache fills up, the server uses the following procedure
+to locate a cache entry to use:
+
+@itemize @bullet
+@item
+Tables that are not currently in use are released, in least-recently-used
+order.
+
+@item
+If the cache is full and no tables can be released, but a new table needs to
+be opened, the cache is temporarily extended as necessary.
+
+@item
+If the cache is in a temporarily-extended state and a table goes from in-use
+to not-in-use state, the table is closed and released from the cache.
+@end itemize
+
+A table is opened for each concurrent access. This means that
+if you have two threads accessing the same table or access the table
+twice in the same query (with @code{AS}) the table needs to be opened twice.
+The first open of any table takes two file descriptors; each additional
+use of the table takes only one file descriptor. The extra descriptor
+for the first open is used for the index file; this descriptor is shared
+among all threads.
+
+You can check if your table cache is too small by checking the mysqld
+variable @code{opened_tables}. If this is quite big, even if you
+haven't done alot of @code{flush tables}, you should increase your table
+cache. @xref{SHOW STATUS}.
+
+@node Creating many tables, Open tables, Table cache, System
+@subsection Drawbacks of creating large numbers of tables in the same database
+
+If you have many files in a directory, open, close and create operations will
+be slow. If you execute @code{SELECT} statements on many different tables,
+there will be a little overhead when the table cache is full, because for
+every table that has to be opened, another must be closed. You can reduce
+this overhead by making the table cache larger.
+
+@node Open tables, Memory use, Creating many tables, System
+@subsection Why so many open tables?
+
+When you run @code{mysqladmin status}, you'll see something like this:
+
+@example
+Uptime: 426 Running threads: 1 Questions: 11082 Reloads: 1 Open tables: 12
+@end example
+
+This can be somewhat perplexing if you only have 6 tables.
+
+@strong{MySQL} is multithreaded, so it may have many queries on the same
+table simultaneously. To minimize the problem with two threads having
+different states on the same file, the table is opened independently by
+each concurrent thread. This takes some memory and one extra file
+descriptor for the data file. The index file descriptor is shared
+between all threads.
+
+@cindex Memory use
+@node Memory use, Internal locking, Open tables, System
+@subsection How MySQL uses memory
+
+The list below indicates some of the ways that the @code{mysqld} server
+uses memory. Where applicable, the name of the server variable relevant
+to the memory use is given.
+
+@itemize @bullet
+@item
+The key buffer (variable @code{key_buffer_size}) is shared by all
+threads; Other buffers used by the server are allocated as
+needed. @xref{Server parameters}.
+
+@item
+Each connection uses some thread specific space; A stack (default 64K,
+variable @code{thread_stack}) a connection buffer (variable
+@code{net_buffer_length}), and a result buffer (variable
+@code{net_buffer_length}). The connection buffer and result buffer are
+dynamically enlarged up to @code{max_allowed_packet} when needed. When
+a query is running, a copy of the current query string is also allocated.
+
+@item
+All threads share the same base memory.
+
+@item
+Only the compressed ISAM / MyISAM tables are memory mapped. This is
+because the 32-bit memory space of 4GB is not large enough for most
+big tables. When systems with a 64-bit address-space become more
+common we may add general support for memory-mapping.
+
+@item
+Each request doing a sequential scan over a table allocates a read buffer
+(variable @code{record_buffer}).
+
+@item
+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 record length (calculated as the
+sum of all column lengths) or that contain @code{BLOB} columns are
+stored on disk.
+
+One problem in @strong{MySQL} versions before 3.23.2 is that if a HEAP table
+exceeds the size of @code{tmp_table_size}, you get the error @code{The
+table tbl_name is full}. In newer versions this is handled by
+automatically changing the in-memory (HEAP) table to a disk-based
+(MyISAM) table as necessary. To work around this problem, you can
+increase the temporary table size by setting the @code{tmp_table_size}
+option to @code{mysqld}, or by setting the SQL option
+@code{SQL_BIG_TABLES} in the client program. @xref{SET OPTION, ,
+@code{SET OPTION}}. In @strong{MySQL} 3.20, the maximum size of the
+temporary table was @code{record_buffer*16}, so if you are using this
+version, you have to increase the value of @code{record_buffer}. You can
+also start @code{mysqld} with the @code{--big-tables} option to always
+store temporary tables on disk, however, this will affect the speed of
+many complicated queries.
+
+@item
+Most requests doing a sort allocates a sort buffer and 0-2 temporary
+files depending on the result set size. @xref{Temporary files}.
+
+@item
+Almost all parsing and calculating is done in a local memory store. No
+memory overhead is needed for small items and the normal slow memory
+allocation and freeing is avoided. Memory is allocated only for
+unexpectedly large strings (this is done with @code{malloc()} and
+@code{free()}).
+
+@item
+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 of size @code{3 * n} is
+allocated (where @code{n} is the maximum row length, not counting @code{BLOB}
+columns). A @code{BLOB} uses 5 to 8 bytes plus the length of the @code{BLOB}
+data.
+
+@item
+For each table having @code{BLOB} columns, a buffer is enlarged dynamically
+to read in larger @code{BLOB} values. If you scan a table, a buffer as large
+as the largest @code{BLOB} value is allocated.
+
+@item
+Table handlers for all in-use tables are saved in a cache and managed as a
+FIFO. Normally the cache has 64 entries. If a table has been used by two
+running threads at the same time, the cache contains two entries for the
+table. @xref{Table cache}.
+
+@item
+A @code{mysqladmin flush-tables} command closes all tables that are not in
+use and marks all in-use tables to be closed when the currently executing
+thread finishes. This will effectively free most in-use memory.
+@end itemize
+
+@code{ps} and other system status programs may report that @code{mysqld}
+uses a lot of memory. This may be caused by thread-stacks on different
+memory addresses. For example, the Solaris version of @code{ps} counts
+the unused memory between stacks as used memory. You can verify this by
+checking available swap with @code{swap -s}. We have tested
+@code{mysqld} with commercial memory-leakage detectors, so there should
+be no memory leaks.
+
+@node Internal locking, Table locking, Memory use, System
+@subsection How MySQL locks tables
+
+You can find a discussion about different locking methods in the appendix.
+@xref{Locking methods}.
+
+All locking in @strong{MySQL} is deadlock-free. This is managed by always
+requesting all needed locks at once at the beginning of a query and always
+locking the tables in the same order.
+
+The locking method @strong{MySQL} uses for @code{WRITE} locks works as follows:
+
+@itemize @bullet
+@item
+If there are no locks on the table, put a write lock on it.
+@item
+Otherwise, put the lock request in the write lock queue.
+@end itemize
+
+The locking method @strong{MySQL} uses for @code{READ} locks works as follows:
+
+@itemize @bullet
+@item
+If there are no write locks on the table, put a read lock on it.
+@item
+Otherwise, put the lock request in the read lock queue.
+@end itemize
+
+When a lock is released, the lock is made available to the threads
+in the write lock queue, then to the threads in the read lock queue.
+
+This means that if you have many updates on a table, @code{SELECT}
+statements will wait until there are no more updates.
+
+To work around this for the case where you want to do many @code{INSERT} and
+@code{SELECT} operations on a table, you can insert rows in a temporary
+table and update the real table with the records from the temporary table
+once in a while.
+
+This can be done with the following code:
+@example
+mysql> LOCK TABLES real_table WRITE, insert_table WRITE;
+mysql> insert into real_table select * from insert_table;
+mysql> delete from insert_table;
+mysql> UNLOCK TABLES;
+@end example
+
+You can use the @code{LOW_PRIORITY} options with @code{INSERT} if you
+want to prioritize retrieval in some specific cases. @xref{INSERT, ,
+@code{INSERT}}.
+
+You could also change the locking code in @file{mysys/thr_lock.c} to use a
+single queue. In this case, write locks and read locks would have the same
+priority, which might help some applications.
+
+@node Table locking, , Internal locking, System
+@subsection Table locking issues
+
+The table locking code in @strong{MySQL} is deadlock free.
+
+@strong{MySQL} uses table locking (instead of row locking or column
+locking) on all table types, except @code{BDB} tables, to achieve a very
+high lock speed. For large tables, table locking is MUCH better than
+row locking for most applications, but there are of course some
+pitfalls.
+
+For @code{BDB} tables, @strong{MySQL} only uses table locking of you
+explicitely lock the table with @code{LOCK TABLES} or execute an command that
+will modify every row in the table, like @code{ALTER TABLE}.
+
+In @strong{MySQL} 3.23.7 and above, you can insert rows into
+@code{MyISAM} tables at the same time as other threads are reading from
+the table. Note that currently this only works if there are no holes after
+deleted rows in the table at the time the insert is made.
+
+Table locking enables many threads to read from a table at the same
+time, but if a thread wants to write to a table, it must first get
+exclusive access. During the update all other threads that want to
+access this particular table will wait until the update is ready.
+
+As updates on tables normally are considered to be more important than
+@code{SELECT}, all statements that update a table have higher priority
+than statements that retrieve information from a table. This should
+ensure that updates are not 'starved' because one issues a lot of heavy
+queries against a specific table. (You can change this by using
+LOW_PRIORITY with the statement that does the update or
+@code{HIGH_PRIORITY} with the @code{SELECT} statement.
+
+Starting from @strong{MySQL 3.23.7} one can use the
+@code{max_write_lock_count} variable to force @strong{MySQL} to
+temporary give all @code{SELECT} statements, that waits for a table, a
+higher priority after a specific number of inserts on a table.
+
+Table locking is however not very good under the following senario:
+
+@itemize @bullet
+@item
+A client issues a @code{SELECT} that takes a long time to run.
+@item
+Another client then issues an @code{UPDATE} on a used table; This client
+will wait until the @code{SELECT} is finished
+@item
+Another client issues another @code{SELECT} statement on the same table; As
+@code{UPDATE} has higher priority than @code{SELECT}, this @code{SELECT}
+will wait for the @code{UPDATE} to finish. It will also wait for the first
+@code{SELECT} to finish!
+@end itemize
+
+Some possible solutions to this problem are:
+
+@itemize @bullet
+@item
+Try to get the @code{SELECT} statements to run faster; You may have to create
+some summary tables to do this.
+
+@item
+Start @code{mysqld} with @code{--low-priority-updates}. This will give
+all statements that update (modify) a table lower priority than a @code{SELECT}
+statement. In this case the last @code{SELECT} statement in the previous
+scenario would execute before the @code{INSERT} statement.
+
+@item
+You can give a specific @code{INSERT},@code{UPDATE} or @code{DELETE} statement
+lower priority with the @code{LOW_PRIORITY} attribute.
+
+@item
+Start @code{mysqld} with a low value for @strong{max_write_lock_count} to give
+@code{READ} locks after a certain number of @code{WRITE} locks.
+
+@item
+You can specify that all updates from a specific thread should be done with
+low priority by using the SQL command: @code{SET SQL_LOW_PRIORITY_UPDATES=1}.
+@xref{SET OPTION, , @code{SET OPTION}}.
+
+@item
+You can specify that a specific @code{SELECT} is very important with the
+@code{HIGH_PRIORITY} attribute. @xref{SELECT, , @code{SELECT}}.
+
+@item
+If you have problems with @code{INSERT} combined with @code{SELECT},
+switch to use the new @code{MyISAM} tables as these supports concurrent
+@code{SELECT}s and @code{INSERT}s.
+
+@item
+If you mainly mix @code{INSERT} and @code{SELECT} statements, the
+@code{DELAYED} attribute to @code{INSERT} will probably solve your problems.
+@xref{INSERT, , @code{INSERT}}.
+
+@item
+If you have problems with @code{SELECT} and @code{DELETE}, the @code{LIMIT}
+option to @code{DELETE} may help. @xref{DELETE, , @code{DELETE}}.
+@end itemize
+
+@node Data size, MySQL indexes, System, Performance
+@section Get your data as small as possible
+
+One of the most basic optimization is to get your data (and indexes) to
+take as little space on the disk (and in memory) as possible. This can
+give huge improvements because disk reads are faster and normally less
+main memory will be used. Indexing also takes less resources if
+done on smaller columns.
+
+@strong{MySQL} supports a lot of different table types and row formats.
+Choosing the right table format may give you a big performance gain.
+@xref{Table types}.
+
+You can get better performance on a table and minimize storage space
+using the techniques listed below:
+
+@itemize @bullet
+@item
+Use the most efficient (smallest) types possible. @strong{MySQL} has a
+many specialized types that save disk space and memory.
+@item
+Use the smaller integer types if possible to get smaller tables. For
+example, @code{MEDIUMINT} is often better than @code{INT}.
+@item
+Declare columns to be @code{NOT NULL} if possible. It makes everything
+faster and you save one bit per column. Note that if you really need
+@code{NULL} in your application you should definitely use it, just avoid
+having it on all columns by default.
+@item
+If you don't have any variable-length columns (@code{VARCHAR},
+@code{TEXT} or @code{BLOB} columns), a fixed-size record format is
+used. This is faster but unfortunately may waste some space.
+@xref{MyISAM table formats}.
+@item
+Each table should have as short as possible primary index. This makes
+identification of one row easy and efficient.
+@item
+For each table you have to decide which storage/index method to
+use. @xref{Table types}.
+@item
+Only create the indexes that you really need. Indexes are good for
+retrieval but bad when you need to store things fast. If you mostly
+access a table by searching on a combination of columns, make an index
+on them. The first index part should be the most used column. If you are
+ALWAYS using many columns you should use the column with more duplicates
+first to get better compression of the index.
+@item
+If it's very likely that a column has a unique prefix on the first number
+of characters, it's better to only index this prefix. @strong{MySQL}
+supports an index on a part of a character column. Shorter indexes is
+faster not only because they take less disk space but also because they
+will give you more hits in the index cache and thus fewer disk
+seeks. @xref{Server parameters}.
+@item
+In some circumstances it can be beneficial to split a table that is
+scanned very often into two. This is especially true if it is a dynamic
+format table and it is possible to use a smaller static format table that
+can be used to find the relevant rows when scanning the table.
+@end itemize
+
+@node MySQL indexes, Query Speed, Data size, Performance
+@section How @strong{MySQL} uses indexes
+
+Indexes are used to find rows with a specific value of one column
+fast. Without an index @strong{MySQL} has to start with the first record
+and then read through the whole table until it finds the relevent
+rows. The bigger the table, the more this costs. If the table has an index
+for the colums in question, @strong{MySQL} can get fast a position to
+seek to in the middle of the data file without having to look at all the
+data. If a table has 1000 rows this is at least 100 times faster than
+reading sequentially. Note that if you need to access almost all 1000
+rows it is faster to read sequentially because we then avoid disk seeks.
+
+All @strong{MySQL} indexes (@code{PRIMARY}, @code{UNIQUE} and
+@code{INDEX}) are stored in B-trees. Strings are automatically prefix-
+and end-space compressed. @xref{CREATE INDEX, , @code{CREATE INDEX}}.
+
+Indexes are used to:
+@itemize @bullet
+@item
+Quickly find the rows that match a @code{WHERE} clause.
+
+@item
+Retrieve rows from other tables when performing joins.
+
+@item
+Find the @code{MAX()} or @code{MIN()} value for a specific indexed
+column.
+@example
+SELECT MIN(key_part2),MAX(key_part2) FROM table_name where key_part1=10
+@end example
+
+@item
+Sort or group a table if the sorting or grouping is done on a leftmost
+prefix of a usable key (e.g., @code{ORDER BY key_part_1,key_part_2 }). The
+key is read in reverse order if all key parts are followed by @code{DESC}.
+
+The index can also be used even if the @code{ORDER BY} doesn't match gthe index
+exactly, as long as all the not used index parts and all the extra
+are @code{ORDER BY} columns are constants in the @code{WHERE} clause. The
+following queries will use the index to resolve the @code{ORDER BY} part.
+
+@example
+SELECT * FROM foo ORDER BY key_part1,key_part2,key_part3;
+SELECT * FROM foo WHERE column=constant ORDER BY column, key_part1;
+SELECT * FROM foo WHERE key_part1=const GROUP BY key_part2;
+@end example
+
+@item
+In some cases a query can be optimized to retrieve values without
+consulting the data file. If all used columns for some table are numeric
+and form a leftmost prefix for some key, the values may be retrieved
+from the index tree for greater speed.
+
+@example
+SELECT key_part3 FROM table_name WHERE key_part1=1
+@end example
+
+@end itemize
+
+Suppose you issue the following @code{SELECT} statement:
+
+@example
+mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
+@end example
+
+If a multiple-column index exists on @code{col1} and @code{col2}, the
+appropriate rows can be fetched directly. If separate single-column
+indexes exist on @code{col1} and @code{col2}, the optimizer tries to
+find the most restrictive index by deciding which index will find fewer
+rows and using that index to fetch the rows.
+
+@cindex Indexes, leftmost prefix of
+@cindex Leftmost prefix of indexes
+If the table has a multiple-column index, any leftmost prefix of the
+index can be used by the optimizer to find rows. For example, if you
+have a three-column index on @code{(col1,col2,col3)}, you have indexed
+search capabilities on @code{(col1)}, @code{(col1,col2)} and
+@code{(col1,col2,col3)}.
+
+@strong{MySQL} can't use a partial index if the columns don't form a
+leftmost prefix of the index. Suppose you have the @code{SELECT}
+statements shown below:
+
+@example
+mysql> SELECT * FROM tbl_name WHERE col1=val1;
+mysql> SELECT * FROM tbl_name WHERE col2=val2;
+mysql> SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
+@end example
+
+If an index exists on @code{(col1,col2,col3)}, only the first query
+shown above uses the index. The second and third queries do involve
+indexed columns, but @code{(col2)} and @code{(col2,col3)} are not
+leftmost prefixes of @code{(col1,col2,col3)}.
+
+@findex LIKE, and indexes
+@findex LIKE, and wildcards
+@cindex Indexes, and @code{LIKE}
+@cindex Wildcards, and @code{LIKE}
+@strong{MySQL} also uses indexes for @code{LIKE} comparisons if the argument
+to @code{LIKE} is a constant string that doesn't start with a wildcard
+character. For example, the following @code{SELECT} statements use indexes:
+
+@example
+mysql> select * from tbl_name where key_col LIKE "Patrick%";
+mysql> select * from tbl_name where key_col LIKE "Pat%_ck%";
+@end example
+
+In the first statement, only rows with @code{"Patrick" <= key_col <
+"Patricl"} are considered. In the second statement, only rows with
+@code{"Pat" <= key_col < "Pau"} are considered.
+
+The following @code{SELECT} statements will not use indexes:
+@example
+mysql> select * from tbl_name where key_col LIKE "%Patrick%";
+mysql> select * from tbl_name where key_col LIKE other_col;
+@end example
+
+In the first statement, the @code{LIKE} value begins with a wildcard character.
+In the second statement, the @code{LIKE} value is not a constant.
+
+@findex IS NULL, and indexes
+@cindex Indexes, and @code{IS NULL}
+Searching using @code{column_name IS NULL} will use indexes if column_name
+is an index.
+
+@strong{MySQL} normally uses the index that finds least number of rows. An
+index is used for columns that you compare with the following operators:
+@code{=}, @code{>}, @code{>=}, @code{<}, @code{<=}, @code{BETWEEN} and a
+@code{LIKE} with a non-wildcard prefix like @code{'something%'}.
+
+Any index that doesn't span all @code{AND} levels in the @code{WHERE} clause
+is not used to optimize the query. In other words: To be able to use an
+index, a prefix of the index must be used in every @code{AND} group.
+
+The following @code{WHERE} clauses use indexes:
+@example
+... WHERE index_part1=1 AND index_part2=2 AND other_column=3
+... WHERE index=1 OR A=10 AND index=2 /* index = 1 OR index = 2 */
+... WHERE index_part1='hello' AND index_part_3=5
+ /* optimized like "index_part1='hello'" */
+... WHERE index1=1 and index2=2 or index1=3 and index3=3;
+ /* Can use index on index1 but not on index2 or index 3 */
+@end example
+
+These @code{WHERE} clauses do @strong{NOT} use indexes:
+@example
+... WHERE index_part2=1 AND index_part3=2 /* index_part_1 is not used */
+... WHERE index=1 OR A=10 /* Index is not used in both AND parts */
+... WHERE index_part1=1 OR index_part2=10 /* No index spans all rows */
+@end example
+
+Note that in some cases @code{MySQL} will not use an index, even if one
+would be available. Some of the cases where this happens are:
+
+@itemize @bullet
+@item
+If the use of the index, would require @strong{MySQL} to access more
+than 30 % of the rows in the table. (In this case a table scan is
+probably much faster as this will require us to do much fewer seeks).
+Note that if you with such a query use @code{LIMIT} to only retrieve
+part of the rows, @strong{MySQL} will use an index anyway as it can this
+way much more quickly find the few rows to return in the result.
+@end itemize
+
+@node Query Speed, Tips, MySQL indexes, Performance
+@section Speed of queries that access or update data
+
+First, one thing that affects all queries: The more complex permission
+system setup you have, the more overhead you get.
+
+If you do not have any @code{GRANT} statements done @strong{MySQL} will
+optimize the permission checking somewhat. So if you have a very high
+volume it may be worth the time to avoid grants. Otherwise more
+permission check results in a larger overhead.
+
+If your problem is with some explicit @strong{MySQL} function, you can
+always time this in the @strong{MySQL} client:
+
+@example
+mysql> select benchmark(1000000,1+1);
++------------------------+
+| benchmark(1000000,1+1) |
++------------------------+
+| 0 |
++------------------------+
+1 row in set (0.32 sec)
+@end example
+
+The above shows that @strong{MySQL} can execute 1,000,000 @code{+}
+expressions in 0.32 seconds on a @code{PentiumII 400MHz}.
+
+All @strong{MySQL} functions should be very optimized, but there may be
+some exceptions and the @code{benchmark(loop_count,expression)} is a
+great tool to find out if this is a problem with your query.
+
+@menu
+* Estimating performance:: Estimating query performance
+* SELECT speed:: Speed of @code{SELECT} queries
+* Where optimizations:: How MySQL optimizes @code{WHERE} clauses
+* LEFT JOIN optimization:: How MySQL optimizes @code{LEFT JOIN}
+* LIMIT optimization:: How MySQL optimizes @code{LIMIT}
+* Insert speed:: Speed of @code{INSERT} queries
+* Update speed:: Speed of @code{UPDATE} queries
+* Delete speed:: Speed of @code{DELETE} queries
+@end menu
+
+@node Estimating performance, SELECT speed, Query Speed, Query Speed
+@subsection Estimating query performance
+
+In most cases you can estimate the performance by counting disk seeks.
+For small tables you can usually find the row in 1 disk seek (as the
+index is probably cached). For bigger tables, you can estimate that,
+(using B++ tree indexes), you will need: @code{log(row_count) /
+log(index_block_length / 3 * 2 / (index_length + data_pointer_length)) +
+1} seeks to find a row.
+
+In @strong{MySQL} an index block is usually 1024 bytes and the data
+pointer is usually 4 bytes, which gives for a 500,000 row table with a
+index length of 3 (medium integer) gives you:
+@code{log(500,000)/log(1024/3*2/(3+4)) + 1} = 4 seeks.
+
+As the above index would require about 500,000 * 7 * 3/2 = 5.2M,
+(assuming that the index buffers are filled to 2/3 (which is typical)
+you will probably have much of the index in memory and you will probably
+only need 1-2 calls to read data from the OS to find the row.
+
+For writes you will however need 4 seek requests (as above) to find
+where to place the new index and normally 2 seeks to update the index
+and write the row.
+
+Note that the above doesn't mean that your application will slowly
+degenerate by N log N! As long as everything is cached by the OS or SQL
+server things will only go marginally slower while the table gets
+bigger. After the data gets too big to be cached, things will start to
+go much slower until your applications is only bound by disk-seeks
+(which increase by N log N). To avoid this, increase the index cache as
+the data grows. @xref{Server parameters}.
+
+@node SELECT speed, Where optimizations, Estimating performance, Query Speed
+@subsection Speed of @code{SELECT} queries
+
+In general, when you want to make a slow @code{SELECT ... WHERE} faster, the
+first thing to check is whether or not you can add an index. @xref{MySQL
+indexes, , @strong{MySQL} indexes}. All references between different tables
+should usually be done with indexes. You can use the @code{EXPLAIN} command
+to determine which indexes are used for a @code{SELECT}.
+@xref{EXPLAIN, , @code{EXPLAIN}}.
+
+Some general tips:
+
+@itemize @bullet
+@item
+To help @strong{MySQL} optimize queries better, run @code{myisamchk
+--analyze} on a table after it has been loaded with relevant data. This
+updates a value for each index part that indicates the average number of
+rows that have the same value. (For unique indexes, this is always 1,
+of course.). @strong{MySQL} will use this to decide which index to
+choose when you connect two tables with 'a non-constant expression'.
+You can check the result from the @code{analyze} run by doing @code{SHOW
+INDEX FROM table_name} and examining the @code{Cardinality} column.
+
+@item
+To sort an index and data according to an index, use @code{myisamchk
+--sort-index --sort-records=1} (if you want to sort on index 1). If you
+have a unique index from which you want to read all records in order
+according to that index, this is a good way to make that faster. Note
+however that this sorting isn't written optimally and will take a long
+time for a large table!
+@end itemize
+
+@cindex Optimizations
+@node Where optimizations, LEFT JOIN optimization, SELECT speed, Query Speed
+@subsection How MySQL optimizes @code{WHERE} clauses
+
+The @code{WHERE} optimizations are put in the @code{SELECT} part here because
+they are mostly used with @code{SELECT}, but the same optimizations apply for
+@code{WHERE} in @code{DELETE} and @code{UPDATE} statements.
+
+Also note that this section is incomplete. @strong{MySQL} does many
+optimizations and we have not had time to document them all.
+
+Some of the optimizations performed by @strong{MySQL} are listed below:
+
+@itemize @bullet
+@item
+Removal of unnecessary parentheses:
+@example
+ ((a AND b) AND c OR (((a AND b) AND (c AND d))))
+-> (a AND b AND c) OR (a AND b AND c AND d)
+@end example
+@item
+Constant folding:
+@example
+ (a<b AND b=c) AND a=5
+-> b>5 AND b=c AND a=5
+@end example
+@item
+Constant condition removal (needed because of constant folding):
+@example
+ (B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
+-> B=5 OR B=6
+@end example
+@item
+Constant expressions used by indexes are evaluated only once.
+@item
+@code{COUNT(*)} on a single table without a @code{WHERE} is retrieved
+directly from the table information. This is also done for any @code{NOT NULL}
+expression when used with only one table.
+@item
+Early detection of invalid constant expressions. @strong{MySQL} quickly
+detects that some @code{SELECT} statements are impossible and returns no rows.
+@item
+@code{HAVING} is merged with @code{WHERE} if you don't use @code{GROUP BY}
+or group functions (@code{COUNT()}, @code{MIN()}...)
+@item
+For each sub-join, a simpler @code{WHERE} is constructed to get a fast
+@code{WHERE} evaluation for each sub-join and also to skip records as
+soon as possible.
+@cindex Constant table
+@cindex Table, constant
+@item
+All constant tables are read first, before any other tables in the query.
+A constant table is:
+@itemize @minus
+@item
+An empty table or a table with 1 row.
+@item
+A table that is used with a @code{WHERE} clause on a @code{UNIQUE}
+index, or a @code{PRIMARY KEY}, where all index parts are used with constant
+expressions and the index parts are defined as @code{NOT NULL}.
+@end itemize
+All the following tables are used as constant tables:
+@example
+mysql> SELECT * FROM t WHERE primary_key=1;
+mysql> SELECT * FROM t1,t2
+ WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
+@end example
+
+@item
+The best join combination to join the tables is found by trying all
+possibilities. If all columns in @code{ORDER BY} and in @code{GROUP
+BY} come from the same table, then this table is preferred first when
+joining.
+@item
+If there is an @code{ORDER BY} clause and a different @code{GROUP BY} clause,
+or if the @code{ORDER BY} or @code{GROUP BY}
+contains columns from tables other than the first table in the join
+queue, a temporary table is created.
+@item
+If you use @code{SQL_SMALL_RESULT}, @strong{MySQL} will use an in-memory
+temporary table.
+@item
+As @code{DISTINCT} is converted to a @code{GROUP BY} on all columns,
+@code{DISTINCT} combined with @code{ORDER BY} will in many cases also need
+a temporary table.
+@item
+Each table index is queried and the best index that spans fewer than 30% of
+the rows is used. If no such index can be found, a quick table scan is used.
+@item
+In some cases, @strong{MySQL} can read rows from the index without even
+consulting the data file. If all columns used from the index are numeric,
+then only the index tree is used to resolve the query.
+@item
+Before each record is output, those that do not match the @code{HAVING} clause
+are skipped.
+@end itemize
+
+Some examples of queries that are very fast:
+
+@example
+mysql> SELECT COUNT(*) FROM tbl_name;
+mysql> SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;
+mysql> SELECT MAX(key_part2) FROM tbl_name
+ WHERE key_part_1=constant;
+mysql> SELECT ... FROM tbl_name
+ ORDER BY key_part1,key_part2,... LIMIT 10;
+mysql> SELECT ... FROM tbl_name
+ ORDER BY key_part1 DESC,key_part2 DESC,... LIMIT 10;
+@end example
+
+The following queries are resolved using only the index tree (assuming
+the indexed columns are numeric):
+
+@example
+mysql> SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;
+mysql> SELECT COUNT(*) FROM tbl_name
+ WHERE key_part1=val1 AND key_part2=val2;
+mysql> SELECT key_part2 FROM tbl_name GROUP BY key_part1;
+@end example
+
+The following queries use indexing to retrieve the rows in sorted
+order without a separate sorting pass:
+
+@example
+mysql> SELECT ... FROM tbl_name ORDER BY key_part1,key_part2,...
+mysql> SELECT ... FROM tbl_name ORDER BY key_part1 DESC,key_part2 DESC,...
+@end example
+
+@node LEFT JOIN optimization, LIMIT optimization, Where optimizations, Query Speed
+@subsection How MySQL optimizes @code{LEFT JOIN}
+
+@code{A LEFT JOIN B} is in @strong{MySQL} implemented as follows:
+
+@itemize @bullet
+@item
+The table @code{B} is set to be dependent on table @code{A} and all tables
+that @code{A} is dependent on.
+@item
+The table @code{A} is set to be dependent on all tables (except @code{B})
+that are used in the @code{LEFT JOIN} condition.
+@item
+All @code{LEFT JOIN} conditions are moved to the @code{WHERE} clause.
+@item
+All standard join optimizations are done, with the exception that a table is
+always read after all tables it is dependent on. If there is a circular
+dependence then @strong{MySQL} will issue an error.
+@item
+All standard @code{WHERE} optimizations are done.
+@item
+If there is a row in @code{A} that matches the @code{WHERE} clause, but there
+wasn't any row in @code{B} that matched the @code{LEFT JOIN} condition,
+then an extra @code{B} row is generated with all columns set to @code{NULL}.
+@item
+If you use @code{LEFT JOIN} to find rows that doesn't exist in some
+table and you have the following test: @code{column_name IS NULL} in the
+@code{WHERE} part, where column_name is a column that is declared as
+@code{NOT NULL}, then @code{MySQL} will stop searching after more rows
+(for a particular key combination) after it has found one row that
+matches the @code{LEFT JOIN} condition.
+@end itemize
+
+The table read order forced by @code{LEFT JOIN} and @code{STRAIGHT JOIN} will help
+the join optimizer (which calculates in which order tables should be joined) to do
+its work much more quickly as there are fewer table permutations to check.
+
+Note that the above means that if you do a query of type:
+
+@example
+SELECT * FROM a,b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key) WHERE b.key=d.key
+@end example
+
+Then @strong{MySQL} will do a full scan on @code{b} as the @code{LEFT JOIN} will
+force it to be read before @code{d}.
+
+The fix in this case is to change the query to:
+
+@example
+SELECT * FROM b,a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key) WHERE b.key=d.key
+@end example
+
+@node LIMIT optimization, Insert speed, LEFT JOIN optimization, Query Speed
+@subsection How MySQL optimizes @code{LIMIT}
+
+In some cases @strong{MySQL} will handle the query differently when you are
+using @code{LIMIT #} and not using @code{HAVING}:
+
+@itemize @bullet
+@item
+If you are selecting only a few rows with @code{LIMIT}, @strong{MySQL}
+will use indexes in some cases when it normally would prefer to do a
+full table scan.
+@item
+If you use @code{LIMIT #} with @code{ORDER BY}, @strong{MySQL} will end the
+sorting as soon as it has found the first @code{#} lines instead of sorting
+the whole table.
+@item
+When combining @code{LIMIT #} with @code{DISTINCT}, @strong{MySQL} will stop
+as soon as it finds @code{#} unique rows.
+@item
+In some cases a @code{GROUP BY} can be resolved by reading the key in order
+(or do a sort on the key) and then calculate summaries until the
+key value changes. In this case @code{LIMIT #} will not calculate any
+unnecessary @code{GROUP BY}'s.
+@item
+As soon as @strong{MySQL} has sent the first @code{#} rows to the client, it
+will abort the query.
+@item
+@code{LIMIT 0} will always quickly return an empty set. This is useful
+to check the query and to get the column types of the result columns.
+@item
+The size of temporary tables uses the @code{LIMIT #} to calculate how much
+space is needed to resolve the query.
+@end itemize
+
+@node Insert speed, Update speed, LIMIT optimization, Query Speed
+@subsection Speed of @code{INSERT} queries
+
+The time to insert a record consists approximately of:
+
+@itemize @bullet
+@item
+Connect: (3)
+@item
+Sending query to server: (2)
+@item
+Parsing query: (2)
+@item
+Inserting record: (1 x size of record)
+@item
+Inserting indexes: (1 x number of indexes)
+@item
+Close: (1)
+@end itemize
+
+Where the numbers are somewhat proportional to the overall time. This
+does not take into consideration the initial overhead to open tables
+(which is done once for each concurrently-running query).
+
+The size of the table slows down the insertion of indexes by N log N
+(B-trees).
+
+Some ways to speed up inserts:
+
+@itemize @bullet
+@item
+If you are inserting many rows from the same client at the same time use
+multiple value lists @code{INSERT} statements. This is much faster (many
+times in some cases) than using separate @code{INSERT} statements.
+@item
+If you are inserting a lot of rows from different clients, you can get
+higher speed by using the @code{INSERT DELAYED} statement. @xref{INSERT,
+, @code{INSERT}}.
+@item
+Note that with @code{MyISAM} you can insert rows at the same time
+@code{SELECT}s are running if there are no deleted rows in the tables.
+@item
+When loading a table from a text file, use @code{LOAD DATA INFILE}. This
+is usually 20 times faster than using a lot of @code{INSERT} statements.
+@xref{LOAD DATA, , @code{LOAD DATA}}.
+@item
+It is possible with some extra work to make @code{LOAD DATA INFILE} run even
+faster when the table has many indexes. Use the following procedure:
+
+@enumerate
+@item
+Optionally create the table with @code{CREATE TABLE}. For example using
+@code{mysql} or Perl-DBI.
+
+@item
+Execute a @code{FLUSH TABLES} statement or the shell command @code{mysqladmin
+flush-tables}.
+
+@item
+Use @code{myisamchk --keys-used=0 -rq /path/to/db/tbl_name}. This will
+remove all usage of all indexes from the table.
+
+@item
+Insert data into the table with @code{LOAD DATA INFILE}. This will not
+update any indexes and will therefore be very fast.
+
+@item
+If you are going to only read the table in the future, run @code{myisampack}
+on it to make it smaller. @xref{Compressed format}.
+
+@item
+Recreate the indexes with @code{myisamchk -r -q
+/path/to/db/tbl_name}. This will create the index tree in memory before
+writing it to disk, which is much faster because it avoid lots of disk
+seeks. The resulting index tree is also perfectly balanced.
+
+@item
+Execute a @code{FLUSH TABLES} statement or the shell command @code{mysqladmin
+flush-tables}.
+@end enumerate
+
+This procedure will be built into @code{LOAD DATA INFILE} in some future
+version of MySQL.
+@item
+You can speed up insertions by locking your tables:
+
+@example
+mysql> LOCK TABLES a WRITE;
+mysql> INSERT INTO a VALUES (1,23),(2,34),(4,33);
+mysql> INSERT INTO a VALUES (8,26),(6,29);
+mysql> UNLOCK TABLES;
+@end example
+
+The main speed difference is that the index buffer is flushed to disk only
+once, after all @code{INSERT} statements have completed. Normally there would
+be as many index buffer flushes as there are different @code{INSERT}
+statements. Locking is not needed if you can insert all rows with a single
+statement.
+
+Locking will also lower the total time of multi-connection tests, but the
+maximum wait time for some threads will go up (because they wait for
+locks). For example:
+
+@example
+thread 1 does 1000 inserts
+thread 2, 3, and 4 does 1 insert
+thread 5 does 1000 inserts
+@end example
+
+If you don't use locking, 2, 3 and 4 will finish before 1 and 5. If you
+use locking, 2, 3 and 4 probably will not finish before 1 or 5, but the
+total time should be about 40% faster.
+
+As @code{INSERT}, @code{UPDATE} and @code{DELETE} operations are very
+fast in @strong{MySQL}, you will obtain better overall performance by
+adding locks around everything that does more than about 5 inserts or
+updates in a row. If you do very many inserts in a row, you could do a
+@code{LOCK TABLES} followed by a @code{UNLOCK TABLES} once in a while
+(about each 1000 rows) to allow other threads access to the table. This
+would still result in a nice performance gain.
+
+Of course, @code{LOAD DATA INFILE} is much faster still for loading data.
+@end itemize
+
+To get some more speed for both @code{LOAD DATA INFILE} and
+@code{INSERT}, enlarge the key buffer. @xref{Server parameters}.
+
+@node Update speed, Delete speed, Insert speed, Query Speed
+@subsection Speed of @code{UPDATE} queries
+
+Update queries are optimized as a @code{SELECT} query with the additional
+overhead of a write. The speed of the write is dependent on the size of
+the data that is being updated and the number of indexes that are
+updated. Indexes that are not changed will not be updated.
+
+Also another way to get fast updates is to delay updates and then do
+many updates in a row later. Doing many updates in a row is much quicker
+than doing one at a time if you lock the table.
+
+Note that, with dynamic record format, updating a record to
+a longer total length may split the record. So if you do this often
+it is very important to @code{OPTIMIZE TABLE} sometimes.
+@xref{OPTIMIZE TABLE, , @code{OPTIMIZE TABLE}}.
+
+@node Delete speed, , Update speed, Query Speed
+@subsection Speed of @code{DELETE} queries
+
+The time to delete a record is exactly proportional to the number of
+indexes. To delete records more quickly, you can increase the size of
+the index cache. @xref{Server parameters}.
+
+It's also much faster to remove all rows than to remove a big part of the
+rows from a table.
+
+@node Tips, Benchmarks, Query Speed, Performance
+@section Other optimization tips
+
+Unsorted tips for faster systems:
+
+@itemize @bullet
+@item
+Use persistent connections to the database to avoid the connection
+overhead. If you can't use persistent connections and you are doing a
+lot of new connections to the database, you may want to change the value
+of the @code{thread_cache_size} variable. @xref{Server parameters}.
+@item
+Always check that all your queries really use the indexes you have created
+in the tables. In @strong{MySQL} you can do this with the @code{EXPLAIN}
+command. @xref{EXPLAIN, Explain, Explain, manual}.
+@item
+Try to avoid complex @code{SELECT} queries on tables that are updated a
+lot. This is to avoid problems with table locking.
+@item
+The new @code{MyISAM} tables can insert rows in a table without deleted
+rows at the same time another table is reading from it. If this is important
+for you, you should consider methods where you don't have to delete rows
+or run @code{OPTIMIZE TABLE} after you have deleted a lot of rows.
+@item
+In some cases it may make sense to introduce a column that is 'hashed'
+based on information from other columns. If this column is short and
+reasonably unique it may be much faster than a big index on many
+columns. In @strong{MySQL} its very easy to use this extra column:
+@code{SELECT * FROM table_name WHERE hash=MP5(concat(col1,col2))
+AND col_1='constant' AND col_2='constant'}
+@item
+For tables that changes a lot you should try to avoid all @code{VARCHAR}
+or @code{BLOB} columns. You will get dynamic row length as soon as you
+are using a single @code{VARCHAR} or @code{BLOB} columns. @xref{Table
+types}.
+@item
+It's not normally useful to split a table into different tables just
+because the rows gets 'big'. To access a row, the biggest performance
+hit is the disk seek to find the first byte of the row. After finding
+the data most new disks can read the whole row fast enough for most
+applications. The only cases it really matters to split up a table is if
+its a dynamic row size table (see above) that you can change to a fixed
+row size. Or if you very often need to scan the table and don't need
+most of the columns. @xref{Table types}.
+@item
+If you very often need to calculate things based on information from a
+lot of rows (like counts of things) it's probably much better to
+introduce a new table and update the counter in real time. An update of
+type @code{UPDATE table set count=count+1 where index_column=constant}
+is very fast!
+
+This is really important when you use databases like @strong{MySQL} that
+only has table locking (multiple readers / single writers). This will
+also give better performance with most databases as the row locking
+manager in this case will have less to do.
+@item
+If you need to collect statistics from big log tables, use summary tables
+instead of scanning the whole table. Maintaining the summaries should be
+much faster than trying to do statistics 'live'. It's much faster to
+re-generate new summary tables from the logs when things change
+(depending on business decisions) than to have to change the running
+application!
+@item
+If possible one should classify reports as 'live' or 'statistical',
+where data needed for statistical reports are only generated based on
+summary tables that are generated from the actual data.
+@item
+Take advantage of the fact that columns have default values. Insert
+values explicitly only when the value to be inserted differs from the
+default. This reduces the parsing that @strong{MySQL} need to do and
+improves the insert speed.
+@item
+In some cases it's convenient to pack and store data into a blob. In this
+case you have to add some extra code in your appliction to pack/unpack
+things in the blob but this may save a lot of accesses at some stage.
+This is practical when you have data that doesn't conform to a static
+table structure.
+@item
+Normally you should try to keep all data non-redundant (what
+is called 3rd normal form in database theory), but you should not be
+afraid of duplicating things or creating summary tables if you need these
+to gain more speed.
+@item
+Stored procedures or UDF (user defined functions) may be a good way to
+get more performance. In this case you should however always have a way
+to do this some other (slower) way if you use some database that doesn't
+support this.
+@item
+You can always gain something by caching queries/answers in your
+application and trying to do many inserts/updates at the same time. If
+your database supports lock tables (like @strong{MySQL} and Oracle),
+this should help to ensure that the index cache is only flushed once
+after all updates.
+@item
+Use @code{INSERT /*! DELAYED */} when you do not need to know when your
+data is written. This speeds things up because many records can be written
+with a single disk write.
+@item
+Use @code{INSERT /*! LOW_PRIORITY */} when you want your selects to be
+more important.
+@item
+Use @code{SELECT /*! HIGH_PRIORITY */} to get selects that jump the
+queue. That is the select is done even if there is somebody waiting to
+do a write.
+@item
+Use the multi-line @code{INSERT} statement to store many rows with one
+SQL command (many SQL servers supports this).
+@item
+Use @code{LOAD DATA INFILE} to load bigger amounts of data. This is
+faster than normal inserts and will be even faster when @code{myisamchk}
+is integrated in @code{mysqld}.
+@item
+Use @code{AUTO_INCREMENT} columns to make unique values.
+@item
+Use @code{OPTIMIZE TABLE} once in a while to avoid fragmentation when
+using dynamic table format. @xref{OPTIMIZE TABLE, , @code{OPTIMIZE TABLE}}.
+
+@item
+Use @code{HEAP} tables to get more speed when possible. @xref{Table
+types}.
+@item
+When using a normal web server setup, images should be stored as
+files. That is, store only a file reference in the database. The main
+reason for this is that a normal web server is much better at caching
+files than database contents. So it it's much easier to get a fast
+system if you are using files.
+@item
+Use in memory tables for non-critical data that are accessed often (like
+information about the last shown banner for users that doesn't have
+cookies).
+@item
+Columns with identical information in different tables should be
+declared identical and have identical names. Before version 3.23 you
+got slow joins otherwise.
+
+Try to keep the names simple (use @code{name} instead of
+@code{customer_name} in the customer table). To make your names portable
+to other SQL servers you should keep them shorter than 18 characters.
+@item
+If you need REALLY high speed you should take a look at the low level
+interfaces for data storage that the different SQL servers support! For
+example by accessing the @strong{MySQL} @code{MyISAM} directly you could
+get a speed increase of 2-5 times compared to using the SQL interface.
+To be able to do this the data must however be on the same server as
+the application and usually it should only be accessed by one process
+(because external file locking is really slow). One could eliminate the
+above problems by introducing low-level @code{MyISAM} commands in the
+@strong{MySQL} server (this could be one easy way to get more
+performance if needed). By carefully designing the database interface
+it should be quite easy to support this types of optimization.
+@item
+In many cases it's faster to access data from a database (using a live
+connection) than accessing a text file, just because the database is
+likely to be more compact than the text file (if you are using numerical
+data) and this will involve fewer disk accesses. You will also save
+code because you don't have to parse your text files to find line and
+column boundaries.
+@item
+You can also use replication to speed things up. @xref{Replication}.
+@item
+Declaring a table with @code{DELAY_KEY_WRITE=1} will make the updating of
+indexes faster as these are not logged to disk until the file is closed.
+The downside is that you should run @code{myisamchk} on these tables before
+you start @code{mysqld} to ensure that they are okay if something killed
+@code{mysqld} in the middle. As the key information can always be generated
+from the data you should not lose anything by using @code{DELAY_KEY_WRITE}.
+@end itemize
+
+@node Benchmarks, Design, Tips, Performance
+@section Using your own benchmarks
+
+You should definately benchmark your application and database to find
+out where the bottlenecks are. By fixing it (or by replacing the
+bottleneck with a 'dummy module') you can then easily identify the next
+bottleneck (and so on). Even if the overall performance for your
+application is sufficient you should at least make a plan for each
+bottleneck, and decide how to solve it if someday you really need the
+extra performance.
+
+For an example of portable benchmark programs look at the @strong{MySQL}
+benchmark suite. @xref{MySQL Benchmarks, , @strong{MySQL} Benchmarks}. You
+can take any program from this suite and modify it for your needs. By doing this,
+you can try different solutions to your problem and test which is really the
+fastest solution for you.
+
+It is very common that some problems only occur when the system is very
+heavily loaded. We have had many customers who contact us when they
+have a (tested) system in production and have encountered load problems. In
+every one of these cases so far it has been problems with basic design
+(table scans are NOT good at high load) or OS/Library issues. Most of
+this would be a @strong{LOT} easier to fix if the systems were not
+already in production.
+
+To avoid problems like this you should put some effort into benchmarking
+your whole application under the worst possible load! You can use Sasha's
+recent hack for this -
+@uref{http://www.mysql.com/Downloads/Contrib/mysql-bench-0.6.tar.gz, mysql-super-smack}.
+As the name suggests, it can bring your system down to its knees if you ask it,
+so make sure to use it only on your developement systems.
+
+@node Design, Design Limitations, Benchmarks, Performance
+@section Design choices
+
+@strong{MySQL} keeps row data and index data in separate files. Many (almost
+all) other databases mix row and index data in the same file. We believe that
+the @strong{MySQL} choice is better for a very wide range of modern systems.
+
+Another way to store the row data is to keep the information for each
+column in a separate area (examples are SDBM and Focus). This will cause a
+performance hit for every query that accesses more than one column. Because
+this degenerates so quickly when more than one column is accessed,
+we believe that this model is not good for general purpose databases.
+
+The more common case is that the index and data are stored together
+(like in Oracle/Sybase et al). In this case you will find the row
+information at the leaf page of the index. The good thing with this
+layout is that it, in many cases, depending on how well the index is
+cached, saves a disk read. The bad things with this layout is:
+
+@table @bullet
+@item
+Table scanning is much slower because you have to read through the indexes
+to get at the data.
+@item
+You can't use only the index table to retrieve data for a query.
+@item
+You lose a lot of space as you must duplicate indexes from the nodes
+(as you can't store the row in the nodes).
+@item
+Deletes will degenerate the table over time (as indexes in nodes are
+usually not updated on delete).
+@item
+It's harder to cache ONLY the index data.
+@end table
+
+@node Design Limitations, Portability, Design, Performance
+@section MySQL design limitations/tradeoffs
+
+Because @strong{MySQL} uses extremely fast table locking (multiple readers /
+single writers) the biggest remaining problem is a mix of a steady stream of
+inserts and slow selects on the same table.
+
+We believe that for a huge number of systems the extremely fast
+performance in other cases make this choice a win. This case is usually
+also possible to solve by having multiple copies of the table, but it
+takes more effort and hardware.
+
+We are also working on some extensions to solve this problem for some
+common application niches.
+
+@node Portability, Internal use, Design Limitations, Performance
+@section Portability
+
+Because all SQL servers implement different parts of SQL, it takes work to
+write portable SQL applications. For very simple selects/inserts it is
+very easy but the more you need the harder it gets. If you want an
+application that is fast with many databases it becomes even harder!
+
+To make a complex application portable you need to choose a number of
+SQL servers that it should work with.
+
+You can use the @strong{MySQL} crash-me program/web-page
+@uref{http://www.mysql.com/information/crashme/choose.php} to find functions,
+types and limits you can use with a selection of database
+servers. Crash-me now tests far from everything possible but it
+is still comprehensive with about 450 things tested.
+
+For example, you shouldn't have column names longer than 18 characters
+if you want to be able to use Informix or DB2.
+
+Both the @strong{MySQL} benchmarks and crash-me programs are very
+database-independent. By taking a look at how we have handled this, you
+can get a feeling of what you have to do to write your application
+database-independent. The benchmarks themselves can be found in the
+@file{sql-bench} directory in the @strong{MySQL} source
+distribution. They are written in Perl with DBI database interface
+(which solves the access part of the problem).
+
+See @uref{http://www.mysql.com/information/benchmarks.html} the results
+from this benchmark.
+
+As you can see in these results all databases have some weak points. That
+is, they have different design compromises that lead to different
+behavior.
+
+If you strive for database independence you need to get a good feeling
+of each SQL server's bottlenecks. @strong{MySQL} is VERY fast in
+retrieving and updating things, but will have a problem in mixing slow
+readers/writers on the same table. Oracle on the other hand has a big
+problem when you try to access rows that you have recently updated
+(until they are flushed to disk). Transaction databases in general are
+not very good at generating summary tables from log tables as in this
+case row locking is almost useless.
+
+To get your application @emph{really} database-independent you need to define
+an easy extendable interface through which you manipulate your data. As
+C++ is available on most systems, it makes sense to use a C++ classes
+interface to the databases.
+
+If you use some specific feature for some database (like the
+@code{REPLACE} command in @strong{MySQL}), you should code a method for
+the other SQL servers to implement the same feature (but slower). With
+@strong{MySQL} you can use the @code{/*! */} syntax to add
+@strong{MySQL} specific keywords to a query. The code inside
+@code{/**/} will be treated as a comment (ignored) by most other SQL
+servers.
+
+If REAL high performance is more important than exactness, like in some
+web applications, a possibility is to create an application layer that
+caches all results to give you even higher performance. By letting
+old results 'expire' after a while you can keep the cache reasonably
+fresh. This is quite nice in case of extremely high load, in which case
+you can dynamically increase the cache and set the expire timeout higher
+until things get back to normal.
+
+In this case the table creation information should contain information
+of the initial size of the cache and how often the table should normally
+be refreshed.
+
+@node Internal use, , Portability, Performance
+@section What have we used MySQL for?
+
+During @strong{MySQL} initial development, the features of @strong{MySQL} were made to fit
+our largest customer. They handle data warehousing for a couple of the
+biggest retailers in Sweden.
+
+From all stores, we get weekly summaries of all bonus card transactions
+and we are expected to provide useful information for the store owners
+to help them find how their advertisement campaigns are affecting their
+customers.
+
+The data is quite huge (about 7 million summary transactions per month)
+and we have data for 4-10 years that we need to present to the users.
+We got weekly requests from the customers that they want to get
+'instant' access to new reports from this data.
+
+We solved this by storing all information per month in compressed
+'transaction' tables. We have a set of simple macros (script) that
+generates summary tables grouped by different criteria (product group,
+customer id, store ...) from the transaction tables. The reports are
+web pages that are dynamically generated by a small Perl script that
+parses a web page, executes the SQL statements in it and inserts the
+results. We would have used PHP or mod_perl instead but they were
+not available at that time.
+
+For graphical data we wrote a simple tool in @code{C} that can produce
+GIFs based on the result of a SQL query (with some processing of the
+result). This is also dynamically executed from the Perl script that
+parses the @code{HTML} files.
+
+In most cases a new report can simply be done by copying an existing
+script and modifying the SQL query in it. In some cases we will need to
+add more fields to an existing summary table or generate a new one, but
+this is also quite simple as we keep all transactions tables on disk.
+(Currently we have at least 50G of transactions tables and 200G of other
+customer data).
+
+We also let our customers access the summary tables directly with ODBC
+so that the advanced users can themselves experiment with the data.
+
+We haven't had any problems handling this with quite modest Sun Ultra
+SPARCstation (2x200 Mhz). We recently upgraded one of our servers to a 2
+CPU 400 Mhz UltraSPARC and we are now planning to start handling
+transactions on the product level, which would mean a ten-fold increase
+of data. We think we can keep up with this by just adding more disk to
+our systems.
+
+We are also experimenting with Intel-Linux to be able to get more CPU
+power cheaper. Now that we have the binary portable database format (new
+in 3.32) we will start to use this for some parts of the application.
+
+Our initial feelings are that Linux will perform much better on low to
+medium load but Solaris will perform better when you start to get a
+high load because of extreme disk IO, but we don't yet have anything
+conclusive about this. After some discussion with a Linux Kernel
+developer this might be a side effect of Linux giving so much resources
+to the batch job that the interactive performance gets very low. This
+makes the machine feel very slow and unresponsive while big batches are
+going. Hopefully this will be better handled in future Linux Kernels.
+
+@node MySQL Benchmarks, Tools, Performance, Top
+@chapter The MySQL benchmark suite
+
+This should contain a technical description of the @strong{MySQL}
+benchmark suite (and @code{crash-me}) but that description is not
+written yet. Currently, you should look at the code and results in the
+@file{sql-bench} directory in the distribution (and of course on the Web page
+at @uref{http://www.mysql.com/crashme/choose.php} and (normally found in
+the @file{sql-bench} directory in the @strong{MySQL} distribution)).
+
+It is meant to be a benchmark that will tell any user what things a
+given SQL implementation performs well or poorly at.
+
+Note that this benchmark is single threaded so it measures the minimum
+time for the operations.
+
+For example (run on the same NT 4.0 machine):
+
+@multitable @columnfractions .6 .2 .2
+@strong{Reading 2000000 rows by index} @tab @strong{Seconds} @tab @strong{Seconds}
+@item mysql @tab 367 @tab 249
+@item mysql_odbc @tab 464
+@item db2_odbc @tab 1206
+@item informix_odbc @tab 121126
+@item ms-sql_odbc @tab 1634
+@item oracle_odbc @tab 20800
+@item solid_odbc @tab 877
+@item sybase_odbc @tab 17614
+@end multitable
+
+@multitable @columnfractions .6 .2 .2
+@strong{Inserting (350768) rows} @tab @strong{Seconds} @tab @strong{Seconds}
+@item mysql @tab 381 @tab 206
+@item mysql_odbc @tab 619
+@item db2_odbc @tab 3460
+@item informix_odbc @tab 2692
+@item ms-sql_odbc @tab 4012
+@item oracle_odbc @tab 11291
+@item solid_odbc @tab 1801
+@item sybase_odbc @tab 4802
+@end multitable
+
+In the above test @strong{MySQL} was run with a 8M index cache.
+
+Note that Oracle is not included because they asked to be removed. All
+Oracle benchmarks has to be passed by Oracle! We believe that makes
+Oracle benchmarks @strong{VERY} biased because the above benchmarks are
+supposed to show what a standard installation can do for a single
+client.
+
+@code{crash-me} tries to determine what features a database supports and
+what it's capabilities and limitations are by actually running
+queries. For example, it determines:
+
+@itemize @bullet
+@item
+What column types are supported
+@item
+How many indexes are supported
+@item
+What functions are supported
+@item
+How big a query can be
+@item
+How big a @code{VARCHAR} column can be
+@end itemize
+
+@node Tools, Maintenance, MySQL Benchmarks, Top
+@chapter MySQL Utilites
+
+@menu
+* Programs:: What do the executables do?
+* mysql:: The command line tool
+* mysqladmin:: Administering a @strong{MySQL} server
+* mysqldump:: Dumping the structure and data from @strong{MySQL} databases and tables
+* mysqlimport:: Importing data from text files
+* mysqlshow:: Showing databases, tables and columns
+* myisampack:: The @strong{MySQL} compressed read-only table generator
+@end menu
+
+@cindex Environment variables
+@node Programs, mysql, Tools, Tools
+@section Overview of the different MySQL programs
+
+All @strong{MySQL} clients that communicate with the server using the
+@code{mysqlclient} library use the following environment variables:
+
+@tindex MYSQL_UNIX_PORT environment variable
+@tindex Environment variable, MYSQL_UNIX_PORT
+@tindex MYSQL_TCP_PORT environment variable
+@tindex Environment variable, MYSQL_TCP_PORT
+@tindex MYSQL_PWD environment variable
+@tindex Environment variable, MYSQL_PWD
+@tindex MYSQL_DEBUG environment variable
+@tindex Environment variable, MYSQL_DEBUG
+@multitable @columnfractions .25 .75
+@item @strong{Name} @tab @strong{Description}
+@item @code{MYSQL_UNIX_PORT} @tab The default socket; used for connections to @code{localhost}
+@item @code{MYSQL_TCP_PORT} @tab The default TCP/IP port
+@item @code{MYSQL_PWD} @tab The default password
+@item @code{MYSQL_DEBUG} @tab Debug-trace options when debugging
+@item @code{TMPDIR} @tab The directory where temporary tables/files are created
+@end multitable
+
+Use of @code{MYSQL_PWD} is insecure.
+@xref{Connecting}.
+
+@tindex MYSQL_HISTFILE environment variable
+@tindex Environment variable, MYSQL_HISTFILE
+@tindex HOME environment variable
+@tindex Environment variable, HOME
+@cindex History file
+@cindex Command line history
+@tindex .mysql_history file
+The @file{mysql} client uses the file named in the @code{MYSQL_HISTFILE}
+environment variable to save the command line history. The default value for
+the history file is @file{$HOME/.mysql_history}, where @code{$HOME} is the
+value of the @code{HOME} environment variable. @xref{Environment variables}.
+
+All @strong{MySQL} programs take many different options. However, every
+@strong{MySQL} program provides a @code{--help} option that you can use
+to get a full description of the program's different options. For example, try
+@code{mysql --help}.
+
+You can override default options for all standard client programs with an
+option file. @ref{Option files}.
+
+The list below briefly describes the @strong{MySQL} programs:
+
+@table @code
+
+@cindex @code{myisamchk}
+@item myisamchk
+Utility to describe, check, optimize and repair @strong{MySQL} tables.
+Because @code{myisamchk} has many functions, it is described in its own
+chapter. @xref{Maintenance}.
+
+@cindex @code{make_binary_distribution}
+@item make_binary_distribution
+Makes a binary release of a compiled @strong{MySQL}. This could be sent
+by FTP to @file{/pub/mysql/Incoming} on @code{support.mysql.com} for the
+convenience of other @strong{MySQL} users.
+
+@cindex @code{msql2mysql}
+@item msql2mysql
+A shell script that converts @code{mSQL} programs to @strong{MySQL}. It doesn't
+handle all cases, but it gives a good start when converting.
+
+@cindex @code{mysqlaccess}
+@item mysqlaccess
+A script that checks the access privileges for a host, user and database
+combination.
+
+@cindex @code{mysqladmin}
+@item mysqladmin
+Utility for performing administrative operations, such as creating or
+dropping databases, reloading the grant tables, flushing tables to disk and
+reopening log files. @code{mysqladmin} can also be used to retrieve version,
+process and status information from the server.
+@xref{mysqladmin, , @code{mysqladmin}}.
+
+@cindex @code{mysqlbug}
+@item mysqlbug
+The @strong{MySQL} bug report script. This script should always be used when
+filing a bug report to the @strong{MySQL} list.
+
+@cindex @code{mysqld}
+@item mysqld
+The SQL daemon. This should always be running.
+
+@cindex @code{mysqldump}
+@item mysqldump
+Dumps a @strong{MySQL} database into a file as SQL statements or
+as tab-separated text files. Enhanced freeware originally by Igor Romanenko.
+@xref{mysqldump, , @code{mysqldump}}.
+
+@cindex @code{mysqlimport}
+@item mysqlimport
+Imports text files into their respective tables using @code{LOAD DATA
+INFILE}. @xref{mysqlimport, , @code{mysqlimport}}.
+
+@cindex @code{mysqlshow}
+@item mysqlshow
+Displays information about databases, tables, columns and indexes.
+
+@cindex @code{mysql_install_db}
+@item mysql_install_db
+Creates the @strong{MySQL} grant tables with default privileges. This is
+usually executed only once, when first installing @strong{MySQL}
+on a system.
+
+@cindex @code{replace}
+@item replace
+A utility program that is used by @code{msql2mysql}, but that has more
+general applicability as well. @code{replace} changes strings in place in
+files or on the standard input. Uses a finite state machine to match longer
+strings first. Can be used to swap strings. For example, this command
+swaps @code{a} and @code{b} in the given files:
+
+@example
+shell> replace a b b a -- file1 file2 ...
+@end example
+
+@cindex @code{safe_mysqld}
+
+@item safe_mysqld
+A script that starts the @code{mysqld} daemon with some safety features, such
+as restarting the server when an error occurs and logging runtime information
+to a log file.
+@end table
+
+@cindex Scripts
+@cindex @code{mysql}
+@node mysql, mysqladmin, Programs, Tools
+@section The command line tool
+
+@code{mysql} is a simple SQL shell (with GNU @code{readline} capabilities).
+It supports interactive and non-interactive use. When used interactively,
+query results are presented in an ASCII-table format. When used
+non-interactively (e.g., as a filter), the result is presented in
+tab-separated format. (The output format can be changed using command-line
+options.) You can run scripts simply like this:
+
+@example
+shell> mysql database < script.sql > output.tab
+@end example
+
+If you have problems due to insufficient memory in the client, use the
+@code{--quick} option! This forces @code{mysql} to use
+@code{mysql_use_result()} rather than @code{mysql_store_result()} to
+retrieve the result set.
+
+Using @code{mysql} is very easy; Just start it as follows
+@code{mysql database} or @code{mysql --user=user_name --password=your_password database}. Type a SQL statement, end it with @samp{;}, @samp{\g} or @samp{\G}
+and press return/enter.
+
+@code{mysql} supports the following options:
+
+@table @code
+@item -?, --help
+Display this help and exit
+@item -A, --no-auto-rehash
+No automatic rehashing. One has to use 'rehash' to get table and field
+completion. This gives a quicker start of mysql.
+@item -B, --batch
+Print results with a tab as separator, each row on a new line. Doesn't use
+history file.
+@item -C, --compress
+Use compression in server/client protocol.
+@item -#, --debug[=...]
+Debug log. Default is 'd:t:o,/tmp/mysql.trace'
+@item -D, --database=..
+Database to use; This is mainly useful in the @code{my.cnf} file.
+@item -e, --execute=...
+Execute command and quit. (Output like with --batch)
+@item -E, --vertical
+Print the output of a query (rows) vertically. Without this option you
+can also force this output by ending your statements with @code{\G}.
+@item -f, --force
+Continue even if we get a SQL error.
+@item -i, --ignore-space
+Ignore space after function names.
+@item -h, --host=...
+Connect to the given host.
+@item -H, --html
+Produce HTML output.
+@item -L, --skip-line-numbers
+Don't write line number for errors. Useful when one want's to compare result
+files that includes error messages.
+@item -n, --unbuffered
+Flush buffer after each query.
+@item -N, --skip-column-names
+Don't write column names in results.
+@item -O, --set-variable var=option
+Give a variable a value. @code{--help} lists variables.
+@item -o, --one-database
+Only update the default database. This is useful for skipping updates to
+other database in the update log.
+@item
+@item -p[password], --password[=...]
+Password to use when connecting to server. If password is not given on
+the command line, you will be prompted for it. Note that if you use the
+short form @code{-p} you can't have a space between the option and the
+password.
+@item -P --port=...
+TCP/IP port number to use for connection.
+@item -q, --quick
+Don't cache result, print it row-by-row. This may slow down the server
+if the output is suspended. Doesn't use history file.
+@item -r, --raw
+Write column values without escape conversion. Used with @code{--batch}
+@item -s, --silent
+Be more silent.
+@item -S --socket=...
+Socket file to use for connection.
+@item -t --table
+Output in table format. This is default in non-batch mode.
+@item -T, --exit-info
+Only used when debugging. --exit-info=0 will print some usage information
+on exit.
+@item -u, --user=#
+User for login if not current user.
+@item -U, --safe-updates[=#], --i-am-a-dummy[=#]
+Only allow @code{UPDATE} and @code{DELETE} that uses keys. See below for
+more information about this option. You can reset this option if you have
+it in your @code{my.cnf} file by using @code{--safe-updates=0}.
+@item -v, --verbose
+More verbose output (-v -v -v gives the table output format).
+@item -V, --version
+Output version information and exit.
+@item -w, --wait
+Wait and retry if connection is down instead of aborting.
+@end table
+
+If you type 'help' on the command line, @code{mysql} will print out the
+commands that it supports:
+
+@example
+mysql> help
+
+MySQL commands:
+help (\h) Display this text
+? (\h) Synonym for `help'
+clear (\c) Clear command
+connect (\r) Reconnect to the server. Optional arguments are db and host
+edit (\e) Edit command with $EDITOR
+exit (\q) Exit mysql. Same as quit
+go (\g) Send command to mysql server
+ego (\G) Send command to mysql server; Display result vertically
+print (\p) Print current command
+quit (\q) Quit mysql
+rehash (\#) Rebuild completion hash
+source (\.) Execute a SQL script file. Takes a file name as an argument
+status (\s) Get status information from the server
+use (\u) Use another database. Takes database name as argument
+@end example
+
+The @code{status} command gives you some information about the
+connection and the server you are using. If you are running in the
+@code{--safe-updates} mode, @code{status} will also print the values for
+the @code{mysql} variables that affects your queries.
+
+A useful startup option for beginners (introduced in @strong{MySQL} 3.23.11) is
+@code{--safe-mode} (or @code{--i-am-a-dummy} for users that has at some
+time done a @code{DELETE FROM table_name} but forgot the @code{WHERE}
+clause. When using this option, @code{mysql} sends the following
+command to the @strong{MySQL} server when opening the connection:
+
+@example
+SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=#select_limit#,
+ SQL_MAX_JOIN_SIZE=#max_join_size#"
+@end example
+
+where @code{#select_limit#} and @code{#max_join_size#} are variables that
+can be set from the @code{mysql} command line. @xref{SET OPTION, @code{SET}}.
+
+The effect of the above is:
+
+@itemize @bullet
+@item
+You are not allowed to do an @code{UPDATE} or @code{DELETE} statements
+if you don't have a key constraint in the @code{WHERE} part. One can
+however force an @code{UPDATE/DELETE} by using @code{LIMIT}:
+@example
+UPDATE table_name SET not_key_column=# WHERE not_key_column=# LIMIT 1;
+@end example
+@item
+All big results are automatically limited to @code{#select_limit#} rows.
+@item
+@code{SELECT}'s that will probably need to examine more than
+@code{#max_join_size} row combinations will be aborted.
+@end itemize
+
+@node mysqladmin, mysqldump, mysql, Tools
+@section Administering a MySQL server
+
+Utility for performing administrative operations. The syntax is:
+
+@example
+shell> mysqladmin [OPTIONS] command [command-option] command ...
+@end example
+
+You can get a list of the options your version of @code{mysqladmin} supports
+by executing @code{mysqladmin --help}.
+
+The current @code{mysqladmin} supports the following commands:
+
+@multitable @columnfractions .3 .7
+@item create databasename @tab Create a new database.
+@item drop databasename @tab Delete a database and all its tables.
+@item extended-status @tab Gives an extended status message from the server.
+@item flush-hosts @tab Flush all cached hosts.
+@item flush-logs @tab Flush all logs.
+@item flush-tables @tab Flush all tables.
+@item flush-privileges @tab Reload grant tables (same as reload).
+@item kill id,id,... @tab Kill mysql threads.
+@item password @tab new-password Change old password to new-password.
+@item ping @tab Check if mysqld is alive.
+@item processlist @tab Show list of active threads in server.
+@item reload @tab Reload grant tables.
+@item refresh @tab Flush all tables and close and open logfiles.
+@item shutdown @tab Take server down.
+@item slave-start @tab Start slave replication thread.
+@item slave-stop @tab Stop slave replication thread.
+@item status @tab Gives a short status message from the server.
+@item variables @tab Prints variables available.
+@item version @tab Get version info from server.
+@end multitable
+
+All commands can be shortened to their unique prefix. For example:
+
+@example
+shell> mysqladmin proc stat
++----+-------+-----------+----+-------------+------+-------+------+
+| Id | User | Host | db | Command | Time | State | Info |
++----+-------+-----------+----+-------------+------+-------+------+
+| 6 | monty | localhost | | Processlist | 0 | | |
++----+-------+-----------+----+-------------+------+-------+------+
+Uptime: 10077 Threads: 1 Questions: 9 Slow queries: 0 Opens: 6 Flush tables: 1 Open tables: 2 Memory in use: 1092K Max memory used: 1116K
+@end example
+
+The @code{mysqladmin status} command result has the following columns:
+
+@multitable @columnfractions .3 .7
+@item Uptime @tab Number of seconds the @strong{MySQL} server has been up.
+@item Threads @tab Number of active threads (clients).
+@item Questions @tab Number of questions from clients since @code{mysqld} was started.
+@item Slow queries @tab Queries that have taken more than @code{long_query_time} seconds.
+@item Opens @tab How many tables @code{mysqld} has opened.
+@item Flush tables @tab Number of @code{flush ...}, @code{refresh} and @code{reload} commands.
+@item Open tables @tab Number of tables that are open now.
+@item Memory in use @tab Memory allocated directly by the mysqld code (only available when @strong{MySQL} is compiled with --with-debug).
+@item Max memory used @tab Maximum memory allocated directly by the mysqld code (only available when @strong{MySQL} is compiled with --with-debug).
+@end multitable
+
+If you do @code{myslqadmin shutdown} on a socket (in other words, on a
+the computer where @code{mysqld} is running), @code{mysqladmin} will
+wait until the @code{MySQL} @code{pid-file} is removed to ensure that
+the @code{mysqld server} has stopped properly.
+
+@node mysqldump, mysqlimport, mysqladmin, Tools
+@section Dumping the structure and data from MySQL databases and tables
+
+Utility to dump a database or a collection of database for backup or
+for transferring the data to another SQL server. The dump will contain SQL
+statements to create the table and/or populate the table.
+
+@example
+shell> mysqldump [OPTIONS] database [tables]
+OR mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]
+OR mysqldump [OPTIONS] --all-databases [OPTIONS]
+@end example
+
+If you don't give any tables or use the @code{--databases} or
+@code{--all-databases}, the whole database(s) will be dumped.
+
+You can get a list of the options your version of @code{mysqldump} supports
+by executing @code{mysqldump --help}.
+
+Note that if you run @code{mysqldump} without @code{--quick} or
+@code{--opt}, @code{mysqldump} will load the whole result set into
+memory before dumping the result. This will probably be a problem if
+you are dumping a big database.
+
+@code{mysqldump} supports the following options:
+
+@table @code
+@item --add-locks
+Add @code{LOCK TABLES} before and @code{UNLOCK TABLE} after each table dump.
+(To get faster inserts into @strong{MySQL}).
+@item --add-drop-table
+Add a @code{drop table} before each create statement.
+@item -A, --all-databases
+Dump all the databases. This will be same as @code{--databases} with all
+databases selected.
+@item -a, --all
+Include all @strong{MySQL} specific create options.
+@item --allow-keywords
+Allow creation of column names that are keywords. This works by
+prefixing each column name with the table name.
+@item -c, --complete-insert
+Use complete insert statements (with column names).
+@item -C, --compress
+Compress all information between the client and the server if both support
+compression.
+@item -B, --databases
+To dump several databases. Note the difference in usage; In this case
+no tables are given. All name arguments are regarded as databasenames.
+@code{USE db_name;} will be included in the output before each new database.
+@item --delayed
+Insert rows with the @code{INSERT DELAYED} command.
+@item -e, --extended-insert
+Use the new multiline @code{INSERT} syntax. (Gives more compact and
+faster inserts statements.)
+@item -#, --debug[=option_string]
+Trace usage of the program (for debugging).
+@item --help
+Display a help message and exit.
+@item --fields-terminated-by=...
+@itemx --fields-enclosed-by=...
+@itemx --fields-optionally-enclosed-by=...
+@itemx --fields-escaped-by=...
+@itemx --lines-terminated-by=...
+These options are used with the @code{-T} option and have the same
+meaning as the corresponding clauses for @code{LOAD DATA INFILE}.
+@xref{LOAD DATA, , @code{LOAD DATA}}.
+@item -F, --flush-logs
+Flush log file in the @strong{MySQL} server before starting the dump.
+@item -f, --force,
+Continue even if we get a SQL error during a table dump.
+@item -h, --host=..
+Dump data from the @strong{MySQL} server on the named host. The default host
+is @code{localhost}.
+@item -l, --lock-tables.
+Lock all tables before starting the dump. The tables are locked with
+@code{READ LOCAL} to allow concurrent inserts in the case of @code{MyISAM}
+tables.
+@item -n, --no-create-db
+'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' will not be put in the
+output. The above line will be added otherwise, if --databases or
+--all-databases option was given.
+@item -t, --no-create-info
+Don't write table creation info (The @code{CREATE TABLE} statement.)
+@item -d, --no-data
+Don't write any row information for the table. This is very useful if you
+just want to get a dump of the structure for a table!
+@item --opt
+Same as @code{--quick --add-drop-table --add-locks --extended-insert
+--lock-tables}. Should give you the fastest possible dump for reading
+into a @strong{MySQL} server.
+@item -pyour_pass, --password[=your_pass]
+The password to use when connecting to the server. If you specify
+no @samp{=your_pass} part,
+@code{mysqldump} you will be prompted for a password.
+@item -P port_num, --port=port_num
+The TCP/IP port number to use for connecting to a host. (This is used for
+connections to hosts other than @code{localhost}, for which Unix sockets are
+used.)
+@item -q, --quick
+Don't buffer query, dump directly to stdout; Uses @code{mysql_use_result()}
+to do this.
+@item -S /path/to/socket, --socket=/path/to/socket
+The socket file to use when connecting to @code{localhost} (which is the
+default host).
+@item --tables
+Overrides option --databases (-B).
+@item -T, --tab=path-to-some-directory
+Creates a @code{table_name.sql} file, that contains the SQL CREATE commands,
+and a @code{table_name.txt} file, that contains the data, for each give table.
+@strong{NOTE}: This only works if @code{mysqldump} is run on the same
+machine as the @code{mysqld} daemon. The format of the @code{.txt} file
+is made according to the @code{--fields-xxx} and @code{--lines--xxx} options.
+@item -u user_name, --user=user_name
+The @strong{MySQL} user name to use when connecting to the server. The
+default value is your Unix login name.
+@item -O var=option, --set-variable var=option
+Set the value of a variable. The possible variables are listed below.
+@item -v, --verbose
+Verbose mode. Print out more information what the program does.
+@item -V, --version
+Print version information and exit.
+@item -w, --where='where-condition'
+Dump only selected records; Note that QUOTES are mandatory!
+
+@example
+"--where=user='jimf'" "-wuserid>1" "-wuserid<1"
+@end example
+@item -O net_buffer_length=#, where # < 24M
+When creating multi-row-insert statements (as with option
+@code{--extended-insert} or @code{--opt}), @code{mysqldump} will create
+rows up to @code{net_buffer_length} length. If you increase this
+variable, you should also ensure that the @code{max_allowed_packet}
+variable in the @strong{MySQL} server is bigger than the
+@code{net_buffer_length}.
+@end table
+
+The most normal use of @code{mysqldump} is probably for making a backup of
+whole databases. @xref{Backup}.
+
+@example
+mysqldump --opt database > backup-file.sql
+@end example
+
+However, it's also very useful to populate another @strong{MySQL} server with
+information from a database:
+
+@example
+mysqldump --opt database | mysql ---host=remote-host -C database
+@end example
+
+It is possible to dump several databases with one command:
+
+@example
+mysqldump --databases database1 [database2 database3...] > my_databases.sql
+@end example
+
+If all the databases are wanted, one can use:
+
+@example
+mysqldump --all-databases > all_databases.sql
+@end example
+
+@node mysqlimport, mysqlshow, mysqldump, Tools
+@section Importing data from text files
+
+@code{mysqlimport} provides a command line interface to the @code{LOAD DATA
+INFILE} SQL statement. Most options to @code{mysqlimport} correspond
+directly to the same options to @code{LOAD DATA INFILE}.
+@xref{LOAD DATA, , @code{LOAD DATA}}.
+
+@code{mysqlimport} is invoked like this:
+
+@example
+shell> mysqlimport [options] database textfile1 [textfile2....]
+@end example
+
+For each text file named on the command line,
+@code{mysqlimport} strips any extension from the filename and uses the result
+to determine which table to import the file's contents into. For example,
+files named @file{patient.txt}, @file{patient.text} and @file{patient} would
+all be imported into a table named @code{patient}.
+
+@code{mysqlimport} supports the following options:
+
+@table @code
+@item -c, --columns=...
+This option takes a comma separated list of field names as an argument.
+The field list is passed to LOAD DATA INFILE MySQL sql command, which
+mysqlimport calls MySQL to execute. For more information, please see
+@code{LOAD DATA INFILE}. @xref{LOAD DATA, , @code{LOAD DATA}}.
+@item -C, --compress
+Compress all information between the client and the server if both support
+compression.
+
+@item -#, --debug[=option_string]
+Trace usage of the program (for debugging).
+
+@item -d, --delete
+Empty the table before importing the text file.
+
+@item --fields-terminated-by=...
+@itemx --fields-enclosed-by=...
+@itemx --fields-optionally-enclosed-by=...
+@itemx --fields-escaped-by=...
+@itemx --lines-terminated-by=...
+These options have the same meaning as the corresponding clauses for
+@code{LOAD DATA INFILE}. @xref{LOAD DATA, , @code{LOAD DATA}}.
+
+@item -f, --force
+Ignore errors. For example, if a table for a text file doesn't exist,
+continue processing any remaining files. Without @code{--force},
+@code{mysqlimport} exits if a table doesn't exist.
+
+@item --help
+Display a help message and exit.
+
+@item -h host_name, --host=host_name
+Import data to the @strong{MySQL} server on the named host. The default host
+is @code{localhost}.
+
+@item -i, --ignore
+See the description for the @code{--replace} option.
+
+@item -l, --lock-tables
+Lock @strong{ALL} tables for writing before processing any text files. This
+ensures that all tables are synchronized on the server.
+
+@item -L, --local
+Read input files from the client. By default, text files are assumed to be on
+the server if you connect to @code{localhost} (which is the default host).
+
+@item -pyour_pass, --password[=your_pass]
+The password to use when connecting to the server. If you specify
+no @samp{=your_pass} part,
+@code{mysqlimport} you will be prompted for a password.
+
+@item -P port_num, --port=port_num
+The TCP/IP port number to use for connecting to a host. (This is used for
+connections to hosts other than @code{localhost}, for which Unix sockets are
+used.)
+
+@item -r, --replace
+The @code{--replace} and @code{--ignore} options control handling of input
+records that duplicate existing records on unique key values. If you specify
+@code{--replace}, new rows replace existing rows that have the same unique key
+value. If you specify @code{--ignore}, input rows that duplicate an existing
+row on a unique key value are skipped. If you don't specify either option, an
+error occurs when a duplicate key value is found, and the rest of the text
+file is ignored.
+
+@item -s, --silent
+Silent mode. Write output only when errors occur.
+
+@item -S /path/to/socket, --socket=/path/to/socket
+The socket file to use when connecting to @code{localhost} (which is the
+default host).
+
+@item -u user_name, --user=user_name
+The @strong{MySQL} user name to use when connecting to the server. The
+default value is your Unix login name.
+
+@item -v, --verbose
+Verbose mode. Print out more information what the program does.
+
+@item -V, --version
+Print version information and exit.
+@end table
+
+Here follows a sample run of using @code{mysqlimport}:
+
+@example
+$ mysql --version
+mysql Ver 9.33 Distrib 3.22.25, for pc-linux-gnu (i686)
+$ uname -a
+Linux xxx.com 2.2.5-15 #1 Mon Apr 19 22:21:09 EDT 1999 i586 unknown
+$ mysql -e 'CREATE TABLE imptest(id INT, n VARCHAR(30))' test
+$ ed
+a
+100 Max Sydow
+101 Count Dracula
+.
+w imptest.txt
+32
+q
+$ od -c imptest.txt
+0000000 1 0 0 \t M a x S y d o w \n 1 0
+0000020 1 \t C o u n t D r a c u l a \n
+0000040
+$ mysqlimport --local test imptest.txt
+test.imptest: Records: 2 Deleted: 0 Skipped: 0 Warnings: 0
+$ mysql -e 'SELECT * FROM imptest' test
++------+---------------+
+| id | n |
++------+---------------+
+| 100 | Max Sydow |
+| 101 | Count Dracula |
++------+---------------+
+@end example
+
+@node mysqlshow, myisampack, mysqlimport, Tools
+@section Showing databases, tables and columns
+
+@code{mysqlshow} can be used to quickly look at which databases exist,
+their tables, and the table's columns.
+
+With the @code{mysql} program you can get the same information with the
+@code{SHOW} commands. @xref{SHOW}.
+
+@code{mysqlshow} is invoked like this:
+
+@example
+shell> mysqlshow [OPTIONS] [database [table [column]]]
+@end example
+
+@itemize @bullet
+@item
+If no database is given, all matching databases are shown.
+@item
+If no table is given, all matching tables in database are shown.
+@item
+If no column is given, all matching columns and column types in table
+are shown.
+@end itemize
+
+Note that in newer @strong{MySQL} versions you only see those
+database/tables/columns for which you have some privileges.
+
+If the last argument contains a shell or SQL wildcard (@code{*}, @code{?},
+@code{%} or @code{_}) then only what's matched by the wildcard is shown.
+This may cause some confusion when you try to display the columns for a
+table with a @code{_} as in this case @code{mysqlshow} only shows you
+the table names that matches the pattern. This is easily fixed by
+adding an extra @code{%} last on the command line (as a separate
+argument).
+
+@cindex @code{myisampack}
+@cindex @code{pack_isam}
+@node myisampack, , mysqlshow, Tools
+@section The MySQL compressed read-only table generator.
+
+@code{myisampack} is used to compress MyISAM tables and @code{pack_isam}
+is used to compress ISAM tables. Because ISAM tables are deprecated, we
+will only discuss @code{myisampack} here, but everything said about
+@code{myisampack} should also be true for @code{pack_isam}.
+
+@code{myisampack} works by compressing each column in the table separately.
+The information needed to decompress columns is read into memory when the
+table is opened. This results in much better performance when accessing
+individual records, because you only have to uncompress exactly one record, not
+a much larger disk block like when using Stacker on MS-DOS.
+Usually, @code{myisampack} packs the data file 40%-70%.
+
+@strong{MySQL} uses memory mapping (@code{mmap()}) on compressed tables and
+falls back to normal read/write file usage if @code{mmap()} doesn't work.
+
+There are currently two limitations with @code{myisampack}:
+@itemize @bullet
+@item
+After packing, the table is read only.
+@item
+@code{myisampack} can also pack @code{BLOB} or @code{TEXT} columns. The
+older @code{pack_isam} could not do this.
+@end itemize
+
+Fixing these limitations is on our TODO list but with low priority.
+
+@code{myisampack} is invoked like this:
+
+@example
+shell> myisampack [options] filename ...
+@end example
+
+Each filename should be the name of an index (@file{.MYI}) file. If you
+are not in the database directory, you should specify the pathname to the
+file. It is permissible to omit the @file{.MYI} extension.
+
+@code{myisampack} supports the following options:
+
+@table @code
+@item -b, --backup
+Make a backup of the table as @code{tbl_name.OLD}.
+
+@item -#, --debug=debug_options
+Output debug log. The @code{debug_options} string often is
+@code{'d:t:o,filename'}.
+
+@item -f, --force
+Force packing of the table even if it becomes bigger or if the temporary file
+exists. (@code{myisampack} creates a temporary file named @file{tbl_name.TMD}
+while it compresses the table. If you kill @code{myisampack}, the @file{.TMD}
+file may not be deleted. Normally, @code{myisampack} exits with an error if
+it finds that @file{tbl_name.TMD} exists. With @code{--force},
+@code{myisampack} packs the table anyway.
+
+@item -?, --help
+Display a help message and exit.
+
+@item -j big_tbl_name, --join=big_tbl_name
+Join all tables named on the command line into a single table
+@code{big_tbl_name}. All tables that are to be combined
+MUST be identical (same column names and types, same indexes, etc.).
+
+@item -p #, --packlength=#
+Specify the record length storage size, in bytes. The value should be 1, 2
+or 3. (@code{myisampack} stores all rows with length pointers of 1, 2 or 3
+bytes. In most normal cases, @code{myisampack} can determine the right length
+value before it begins packing the file, but it may notice during the packing
+process that it could have used a shorter length. In this case,
+@code{myisampack} will print a note that the next time you pack the same file,
+you could use a shorter record length.)
+
+@item -s, --silent
+Silent mode. Write output only when errors occur.
+
+@item -t, --test
+Don't pack table, only test packing it.
+
+@item -T dir_name, --tmp_dir=dir_name
+Use the named directory as the location in which to write the temporary table.
+
+@item -v, --verbose
+Verbose mode. Write info about progress and packing result.
+
+@item -V, --version
+Display version information and exit.
+
+@item -w, --wait
+
+Wait and retry if table is in use. If the @code{mysqld} server was
+invoked with the @code{--skip-locking} option, it is not a good idea to
+invoke @code{myisampack} if the table might be updated during the
+packing process.
+@end table
+
+The sequence of commands shown below illustrates a typical table compression
+session:
+
+@example
+shell> ls -l station.*
+-rw-rw-r-- 1 monty my 994128 Apr 17 19:00 station.MYD
+-rw-rw-r-- 1 monty my 53248 Apr 17 19:00 station.MYI
+-rw-rw-r-- 1 monty my 5767 Apr 17 19:00 station.frm
+
+shell> myisamchk -dvv station
+
+MyISAM 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
+Datafile pointer (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
+
+Field 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
+
+shell> myisampack station.MYI
+Compressing station.MYI: (1192 records)
+- Calculating statistics
+
+normal: 20 empty-space: 16 empty-zero: 12 empty-fill: 11
+pre-space: 0 end-space: 12 table-lookups: 5 zero: 7
+Original trees: 57 After join: 17
+- Compressing file
+87.14%
+
+shell> ls -l station.*
+-rw-rw-r-- 1 monty my 127874 Apr 17 19:00 station.MYD
+-rw-rw-r-- 1 monty my 55296 Apr 17 19:04 station.MYI
+-rw-rw-r-- 1 monty my 5767 Apr 17 19:00 station.frm
+
+shell> myisamchk -dvv station
+
+MyISAM 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-lookup 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 always zero 2 9
+21 336 4 always zero 2 9
+22 340 1 3 9
+23 341 8 table-lookup 9 0
+24 349 8 table-lookup 10 0
+25 357 8 always 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-lookup 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 always zero 2 9
+34 392 4 table-lookup 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 always zero 2 9
+40 413 4 no zeros 2 9
+41 417 4 always zero 2 9
+42 421 4 no zeros 2 9
+43 425 4 always 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
+@end example
+
+The information printed by @code{myisampack} is described below:
+
+@table @code
+@item normal
+The number of columns for which no extra packing is used.
+
+@item empty-space
+The number of columns containing
+values that are only spaces; these will occupy 1 bit.
+
+@item empty-zero
+The number of columns containing
+values that are only binary 0's; these will occupy 1 bit.
+
+@item empty-fill
+The number of integer columns that don't occupy the full byte range of their
+type; these are changed to a smaller type (for example, an @code{INTEGER}
+column may be changed to @code{MEDIUMINT}).
+
+@item pre-space
+The number of decimal columns that are stored with leading space. In this
+case, each value will contain a count for the number of leading spaces.
+
+@item end-space
+The number of columns that have a lot of trailing space. In this case, each
+value will contain a count for the number of trailing spaces.
+
+@item table-lookup
+The column had only a small number of different values, and that were
+converted to an @code{ENUM} before Huffman compression.
+
+@item zero
+The number of columns for which all values are zero.
+
+@item Original trees
+The initial number of Huffman trees.
+
+@item After join
+The number of distinct Huffman trees left after joining
+trees to save some header space.
+@end table
+
+After a table has been compressed, @code{myisamchk -dvv} prints additional
+information about each field:
+
+@table @code
+@item Type
+The field type may contain the following descriptors:
+
+@table @code
+@item constant
+All rows have the same value.
+
+@item no endspace
+Don't store endspace.
+
+@item no endspace, not_always
+Don't store endspace and don't do end space compression for all values.
+
+@item no endspace, no empty
+Don't store endspace. Don't store empty values.
+
+@item table-lookup
+The column was converted to an @code{ENUM}.
+
+@item zerofill(n)
+The most significant @code{n} bytes in the value are always 0 and are not
+stored.
+
+@item no zeros
+Don't store zeros.
+
+@item always zero
+0 values are stored in 1 bit.
+@end table
+
+@item Huff tree
+The Huffman tree associated with the field.
+
+@item Bits
+The number of bits used in the Huffman tree.
+@end table
+
+After you have run @code{pack_isam}/@code{myisampack} you must run
+@code{isamchk}/@code{myisamchk} to recreate the index. At this time you
+can also sort the index blocks and create statistics that is needed for
+the @strong{MySQL} optimizer to work more efficiently.
+
+@example
+myisamchk -rq --analyze --sort-index table_name.MYI
+isamchk -rq --analyze --sort-index table_name.ISM
+@end example
+
+After you have installed the packed table into the @strong{MySQL} database
+directory you should do @code{mysqladmin flush-tables} to force @code{mysqld}
+to start using the new table.
+
+@node Maintenance, Adding functions, Tools, Top
+@chapter Maintaining a MySQL installation
+
+@menu
+* Table maintenance:: Table maintenance and crash recovery
+* Maintenance regimen:: Setting up a table maintenance regimen
+* Table-info:: Getting information about a table
+* Crash recovery:: Using @code{myisamchk} for crash recovery
+* Log files:: Log file maintenance
+@end menu
+
+@node Table maintenance, Maintenance regimen, Maintenance, Maintenance
+@section Using @code{myisamchk} for table maintenance and crash recovery
+
+Starting with @strong{MySQL} 3.23.13, you can check tables MyISAM with the
+@code{CHECK TABLE} command. @xref{CHECK TABLE}. You can repair tables
+with the @code{REPAIR TABLE} command. @xref{REPAIR TABLE}.
+
+To check/repair MyISAM tables (@code{.MYI} and @code{.MYD}) you should
+use the @code{myisamchk} utility. To check/repair ISAM tables
+(@code{.ISM} and @code{.ISD}) you should use the @code{isamchk}
+utility. @xref{Table types}.
+
+In the following text we will talk about @code{myisamchk}, but everything
+also applies to the old @code{isamchk}.
+
+You can use the @code{myisamchk} utility to get information about your database
+tables, check and repair them or optimize them. The following sections
+describe how to invoke @code{myisamchk} (including a description of its
+options), how to set up a table maintenance schedule, and how to use
+@code{myisamchk} to perform its various functions.
+
+You can, in most cases, also use the command @code{OPTIMIZE TABLES} to
+optimize and repair tables, but this is not as fast or reliable (in case
+of real fatal errors) as @code{myisamchk}. On the other hand,
+@code{OPTIMIZE TABLE} is easier to use and you don't have to worry about
+flushing tables.
+@xref{OPTIMIZE TABLE, , @code{OPTIMIZE TABLE}}.
+
+@menu
+* myisamchk syntax:: @code{myisamchk} invocation syntax
+* myisamchk memory:: @code{myisamchk} memory usage
+@end menu
+
+@node myisamchk syntax, myisamchk memory, Table maintenance, Table maintenance
+@subsection @code{myisamchk} invocation syntax
+
+@code{myisamchk} is invoked like this:
+
+@example
+shell> myisamchk [options] tbl_name
+@end example
+
+The @code{options} specify what you want @code{myisamchk} to do. They are
+described below. (You can also get a list of options by invoking
+@code{myisamchk --help}.) With no options, @code{myisamchk} simply checks your
+table. To get more information or to tell @code{myisamchk} to take corrective
+action, specify options as described below and in the following sections.
+
+@code{tbl_name} is the database table you want to check. If you run
+@code{myisamchk} somewhere other than in the database directory, you must
+specify the path to the file, because @code{myisamchk} has no idea where your
+database is located. Actually, @code{myisamchk} doesn't care whether or not
+the files you are working on are located in a database directory; you can
+copy the files that correspond to a database table into another location and
+perform recovery operations on them there.
+
+You can name several tables on the @code{myisamchk} command line if you
+wish. You can also specify a name as an index file
+name (with the @file{.MYI} suffix), which allows you to specify all
+tables in a directory by using the pattern @file{*.MYI}.
+For example, if you are in a database directory, you can check all the
+tables in the directory like this:
+
+@example
+shell> myisamchk *.MYI
+@end example
+
+If you are not in the database directory, you can check all the tables there
+by specifying the path to the directory:
+
+@example
+shell> myisamchk /path/to/database_dir/*.MYI
+@end example
+
+You can even check all tables in all databases by specifying a wildcard
+with the path to the @strong{MySQL} data directory:
+
+@example
+shell> myisamchk /path/to/datadir/*/*.MYI
+@end example
+
+@code{myisamchk} supports the following options:
+
+@menu
+* myisamchk general options::
+* myisamchk check options::
+* myisamchk repair options::
+* myisamchk other options::
+@end menu
+
+@node myisamchk general options, myisamchk check options, myisamchk syntax, myisamchk syntax
+@subsubsection General options for myisamchk
+
+@table @code
+@item -# or --debug=debug_options
+Output debug log. The @code{debug_options} string often is
+@code{'d:t:o,filename'}.
+@item -? or --help
+Display a help message and exit.
+@item -O var=option, --set-variable var=option
+Set the value of a variable. The possible variables and their default values
+for myisamchk can be examined with @code{myisamchk --help}.
+@multitable @columnfractions .3 .7
+@item key_buffer_size @tab 523264
+@item read_buffer_size @tab 262136
+@item write_buffer_size @tab 262136
+@item sort_buffer_size @tab 2097144
+@item sort_key_blocks @tab 16
+@item decode_bits @tab 9
+@end multitable
+
+@code{key_buffer_size} is only used when you check the table with @code{-e} or
+repair it with @code{-o}.
+@code{sort_buffer_size} is used when you repair the table with @code{-r}.
+
+If you want a faster repair, set the above variables to about 1/4 of your
+available memory. You can set both variables to big values as only one
+of the above buffers will be used at a time.
+
+@item -s or --silent
+Silent mode. Write output only when errors occur. You can use @code{-s}
+twice (@code{-ss}) to make @code{myisamchk} very silent.
+@item -v or --verbose
+Verbose mode. Print more information. This can be used with @code{-d} and
+@code{-e}. Use @code{-v} multiple times (@code{-vv}, @code{-vvv}) for more
+verbosity!
+@item -V or --version
+Print the @code{myisamchk} version and exit.
+@item -w or, --wait
+Instead of giving an error if the table is locked, wait until the table
+is unlocked before continuing. Note that if you are running @code{mysqld}
+on the table with @code{--skip-locking}, the table is can only be locked
+by another @code{myisamchk} command.
+@end table
+
+@node myisamchk check options, myisamchk repair options, myisamchk general options, myisamchk syntax
+@subsubsection Check options for myisamchk
+
+@table @code
+@item -c or --check
+Check table for errors. This is the default operation if you are not
+giving @code{myisamchk} any options that overrides this.
+
+@item -e or --extend-check
+Check the table VERY thoroughly (which is quite slow if you have many
+indexes). This options should only be used extreme cases. Normally,
+@code{myisamchk} or @code{myisamchk --medium-check} should in most
+cases be able to find out if there is any errors in the table.
+
+If you are using @code{--extended-check} and have much memory, you should
+increase the value of @code{key_buffer_size} a lot!
+
+@item -F or --fast
+Check only tables that hasn't been closed properly.
+@item -C or --check-only-changed
+Check only tables that has changed since last check.
+@item -f or --force
+Restart @code{myisamchk} with @code{-r} (repair) on the table, if
+@code{myisamchk} finds any errors in the table.
+@item -i or --information
+Print informational statistics about the table that is checked.
+@item -m or --medium-check
+Faster than extended-check, but only finds 99.99% of all errors.
+Should however be good enough for most cases.
+@item -U or --update-state
+Store in the @file{.MYI} file when the table was checked and if the
+table was crashed. This should be used to get full benefit of the
+@code{--check-only-changed} option, but you shouldn't use this if
+option if the @code{mysqld} server is using the table and you are
+running @code{mysqld} with @code{--skip-locking}.
+@item -T or --read-only
+Don't mark table as checked. This is useful if you use @code{myisamchk}
+to check a table that is in use by some other application that doesn't
+use locking (like @code{mysqld --skip-locking})
+@end table
+
+@node myisamchk repair options, myisamchk other options, myisamchk check options, myisamchk syntax
+@subsubsection Repair options for myisamchk
+
+The following options are used if you start @code{myisamchk} with
+@code{-r} or @code{-o}:
+
+@table @code
+@item -D # or --data-file-length=#
+Max length of data file (when recreating data file when it's 'full')
+@item -e or --extend-check
+Try to recover every possible row from the data file.
+Normally this will also find a lot of garbage rows; Don't use this option
+if you are not totally desperate.
+@item -f or --force
+Overwrite old temporary files (@code{table_name.TMD}) instead of aborting.
+@item -k # or keys-used=#
+If you are using ISAM, tells the ISAM table handler to update only the
+first @code{#} indexes. If you are using @code{MyISAM} tells which keys
+to use, where each binary bit stands for one key (First key is bit 0).
+This can be used to get faster inserts! Deactivated indexes can be
+reactivated by using @code{myisamchk -r}. keys.
+@item -l or --no-symlinks
+Do not follow symbolic links. Normally @code{myisamchk} repairs the
+table a symlink points at.
+@item -r or --recover
+Can fix almost anything except unique keys that aren't unique.
+(which is a extremely unlikely error with ISAM/MyISAM tables).
+If you want to recover a table, this is the option to try first. Only if
+myisamchk reports that the table can't be recovered by @code{-r}, you
+should then try @code{-o}. (Note that in the unlikely case that @code{-r}
+fails, the data file is still intact).
+If you have lot's of memory, you should increase the size of
+@code{sort_buffer_size}!
+@item -o or --safe-recover
+Uses an old recovery method (reads through all rows in order and updates
+all index trees based on the found rows); this is a magnitude slower
+than @code{-r}, but can handle a couple of very unlikely cases that
+@code{-r} cannot handle. This recovery method also uses much less disk
+space than @code{-r}. Normally one should always first repair with
+@code{-r} and only if this fails use @code{-o}.
+
+If you have lot's of memory, you should increase the size of
+@code{key_buffer_size}!
+@item --character-sets-dir=...
+Directory where character sets are stored.
+@item --set-character-set=name
+Change the character set used by the index
+@item .t or --tmpdir=path
+Path where to store temporary files. If this is not set, @code{myisamchk} will
+use the environment variable @code{TMPDIR} for this.
+@item -q or --quick
+Faster repair by not modifying the data file. One can give a second
+@code{-q} to force @code{myisamchk} to modify the original datafile in case
+of duplicate keys
+@item -u or --unpack
+Unpack file packed with myisampack.
+@end table
+
+@node myisamchk other options, , myisamchk repair options, myisamchk syntax
+@subsubsection Other options for myisamchk
+
+Other actions that @code{myisamchk} can do, besides repair and check tables:
+
+@table @code
+@item -a or --analyze
+Analyze the distribution of keys. This improves join performance by
+enabling the join optimizer to better choose in which order it should
+join the tables and which keys it should use.
+@code{myisamchk --describe --verbose table_name'} or using @code{SHOW KEYS} in
+@strong{MySQL}
+@item -d or --description
+Prints some information about table.
+@item -A or --set-auto-increment[=value]
+Force auto_increment to start at this or higher value. If no value is
+given, then sets the next auto_increment value to the highest used value
+for the auto key + 1.
+@item -S or --sort-index
+Sort the index tree blocks in high-low order.
+This will optimize seeks and will make table scanning by key faster.
+@item -R or --sort-records=#
+Sorts records according to an index. This makes your data much more localized
+and may speed up ranged @code{SELECT} and @code{ORDER BY} operations on
+this index. (It may be VERY slow to do a sort the first time!)
+To find out a table's index numbers, use @code{SHOW INDEX}, which shows a
+table's indexes in the same order that @code{myisamchk} sees them. Indexes are
+numbered beginning with 1.
+@end table
+
+@node myisamchk memory, , myisamchk syntax, Table maintenance
+@subsection @code{myisamchk} memory usage
+
+Memory allocation is important when you run @code{myisamchk}.
+@code{myisamchk} uses no more memory than you specify with the @code{-O}
+options. If you are going to use @code{myisamchk} on very large files,
+you should first decide how much memory you want it to use. The default
+is to use only about 3M to fix things. By using larger values, you can
+get @code{myisamchk} to operate faster. For example, if you have more
+than 32M RAM, you could use options such as these (in addition to any
+other options you might specify):
+
+@example
+shell> myisamchk -O sort=16M -O key=16M -O read=1M -O write=1M ...
+@end example
+
+Using @code{-O sort=16M} should probably be enough for most cases.
+
+Be aware that @code{myisamchk} uses temporary files in @code{TMPDIR}. If
+@code{TMPDIR} points to a memory file system, you may easily get out of
+memory errors. If this happens, set @code{TMPDIR} to point at some directory
+with more space and restart @code{myisamchk}
+
+When repairing, @code{myisamchk} will also nead a lot of diskspace:
+
+@itemize @bullet
+@item
+Double the size of the record file (The original one and a copy). This
+space is not needed if one does a repair with @code{--quick}, as in this
+case only the index file will be recreated. This space is needed on the
+same disk as the original record file!
+@item
+Space for the new index file (that replaces the old one; The old
+index file is truncated at start, so one usually ignore this space).
+This space is needed on the same disk as the original index file!
+@item
+When using @code{--repair} (but not when using @code{--safe-repair}, you
+will need space for a sort buffer for:
+@code{(largest_key + row_pointer_length)*number_of_rows * 2}.
+You can check the length of the keys and the row_pointer_length with
+@code{myisamchk -dv table}.
+This space is allocated on the temporary disk (specified by @code{TMPDIR} or
+@code{--tmpdir=#}).
+@end itemize
+
+If you have a problem with disk space during repair, you can try to use
+@code{--safe-repair} instead of @code{--repair}.
+
+@node Maintenance regimen, Table-info, Table maintenance, Maintenance
+@section Setting up a table maintenance regimen
+
+It is a good idea to perform table checks on a regular basis rather than
+waiting for problems to occur. For maintenance purposes, you can use
+@code{myisamchk -s} to check tables. The @code{-s} option causes
+@code{myisamchk} to run in silent mode, printing messages only when errors
+occur.
+
+@tindex .pid (process ID) file
+It's a good idea to check tables when the server starts up.
+For example, whenever the machine has done a reboot in the middle of an
+update, you usually need to check all the tables that could have been
+affected. (This is an ``expected crashed table''.) You could add a test to
+@code{safe_mysqld} that runs @code{myisamchk} to check all tables that have
+been modified during the last 24 hours if there is an old @file{.pid}
+(process ID) file left after a reboot. (The @file{.pid} file is created by
+@code{mysqld} when it starts up and removed when it terminates normally. The
+presence of a @file{.pid} file at system startup time indicates that
+@code{mysqld} terminated abnormally.)
+
+An even better test would be to check any table whose last-modified time
+is more recent than that of the @file{.pid} file.
+
+You should also check your tables regularly during normal system
+operation. At MySQL AB, we run a @code{cron} job to check all our important
+tables once a week, using a line like this in a @file{crontab} file:
+
+@example
+35 0 * * 0 /path/to/myisamchk -s /path/to/datadir/*/*.MYI
+@end example
+
+This prints out information about crashed tables so we can examine and repair
+them when needed.
+
+As we haven't had any unexpectedly crashed tables (tables that become
+corrupted for reasons other than hardware trouble)
+for a couple of years now (this is really true), once a week is
+more than enough for us.
+
+We recommend that to start with, you execute @code{myisamchk -s} each
+night on all tables that have been updated during the last 24 hours,
+until you come to trust @strong{MySQL} as much as we do.
+
+@node Table-info, Crash recovery, Maintenance regimen, Maintenance
+@section Getting information about a table
+
+To get a description of a table or statistics about it, use the commands shown
+below. We explain some of the information in more detail later.
+
+@table @code
+@item myisamchk -d tbl_name
+Runs @code{myisamchk} in ``describe mode'' to produce a description of your
+table. If you start the @strong{MySQL} server using the @code{--skip-locking}
+option, @code{myisamchk} may report an error for a table that is updated while
+it runs. However, because @code{myisamchk} doesn't change the table in describe
+mode, there isn't any risk of destroying data.
+
+@item myisamchk -d -v tbl_name
+To produce more information about what @code{myisamchk} is doing, add @code{-v}
+to tell it to run in verbose mode.
+
+@item myisamchk -eis tbl_name
+Shows only the most important information from a table. It is slow because it
+must read the whole table.
+
+@item myisamchk -eiv tbl_name
+This is like @code{-eis}, but tells you what is being done.
+@end table
+
+Example of @code{myisamchk -d} output:
+@example
+MyISAM file: company.MYI
+Record format: Fixed length
+Data records: 1403698 Deleted blocks: 0
+Recordlength: 226
+
+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
+@end example
+
+Example of @code{myisamchk -d -v} output:
+@example
+MyISAM file: company
+Record format: Fixed length
+File-version: 1
+Creation time: 1999-10-30 12:12:51
+Recover time: 1999-10-31 19:13:01
+Status: checked
+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
+
+table description:
+Key Start Len Index Type Rec/key Root Blocksize
+1 2 8 unique double 1 15845376 1024
+2 15 10 multip. text packed stripped 2 25062400 1024
+3 219 8 multip. double 73 40907776 1024
+4 63 10 multip. text packed stripped 5 48097280 1024
+5 167 2 multip. unsigned short 4840 55200768 1024
+6 177 4 multip. unsigned long 1346 65145856 1024
+7 155 4 multip. text 4995 75090944 1024
+8 138 4 multip. unsigned long 87 85036032 1024
+9 177 4 multip. unsigned long 178 96481280 1024
+ 193 1 text
+@end example
+
+Example of @code{myisamchk -eis} output:
+@example
+Checking MyISAM file: company
+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
+Record blocks: 1403698 Delete blocks: 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 context switches 639, Involuntary context switches 28966
+@end example
+
+Example of @code{myisamchk -eiv} output:
+@example
+Checking MyISAM file: company
+Data records: 1403698 Deleted blocks: 0
+- check file-size
+- check delete-chain
+block_size 1024:
+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
+Record blocks: 1403698 Delete blocks: 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 context switches 10604, Involuntary context switches 122798
+@end example
+
+Here are the sizes of the data and index files for the table used in the
+preceding examples:
+
+@example
+-rw-rw-r-- 1 monty tcx 317235748 Jan 12 17:30 company.MYD
+-rw-rw-r-- 1 davida tcx 96482304 Jan 12 18:35 company.MYM
+@end example
+
+Explanations for the types of information @code{myisamchk} produces are
+given below. The ``keyfile'' is the index file. ``Record'' and ``row''
+are synonymous.
+
+@table @code
+@item ISAM file
+Name of the ISAM (index) file.
+
+@item Isam-version
+Version of ISAM format. Currently always 2.
+
+@item Creation time
+When the data file was created.
+
+@item Recover time
+When the index/data file was last reconstructed.
+
+@item Data records
+How many records are in the table.
+
+@item Deleted blocks
+How many deleted blocks still have reserved space.
+You can optimize your table to minimize this space.
+@xref{Optimization}.
+
+@item Datafile: Parts
+For dynamic record format, this indicates how many data blocks there are. For
+an optimized table without fragmented records, this is the same as @code{Data
+records}.
+
+@item Deleted data
+How many bytes of non-reclaimed deleted data there are.
+You can optimize your table to minimize this space.
+@xref{Optimization}.
+
+@item Datafile pointer
+The size of the data file pointer, in bytes. It is usually 2, 3, 4 or 5
+bytes. Most tables manage with 2 bytes, but this cannot be controlled
+from @strong{MySQL} yet. For fixed tables, this is a record address. For
+dynamic tables, this is a byte address.
+
+@item Keyfile pointer
+The size of the index file pointer, in bytes. It is usually 1, 2 or 3
+bytes. Most tables manage with 2 bytes, but this is calculated
+automatically by @strong{MySQL}. It is always a block address.
+
+@item Max datafile length
+How long the table's data file (@code{.MYD} file) can become, in bytes.
+
+@item Max keyfile length
+How long the table's key file (@code{.MYI} file) can become, in bytes.
+
+@item Recordlength
+How much space each record takes, in bytes.
+
+@item Record format
+The format used to store table rows.
+The examples shown above use @code{Fixed length}.
+Other possible values are @code{Compressed} and @code{Packed}.
+
+@item table description
+A list of all keys in the table. For each key, some low-level information
+is presented:
+
+@table @code
+@item Key
+This key's number.
+
+@item Start
+Where in the record this index part starts.
+
+@item Len
+How long this index part is. For packed numbers, this should always be
+the full length of the column. For strings, it may be shorter than the full
+length of the indexed column, because you can index a prefix of a string
+column.
+
+@item Index
+@code{unique} or @code{multip.} (multiple). Indicates whether or not one value
+can exist multiple times in this index.
+
+@item Type
+What data-type this index part has. This is an ISAM data-type
+with the options @code{packed}, @code{stripped} or @code{empty}.
+
+@item Root
+Address of the root index block.
+
+@item Blocksize
+The size of each index block. By default this is 1024, but the value may be
+changed at compile time.
+
+@item Rec/key
+This is a statistical value used by the optimizer. 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 @code{myisamchk -a}. If this is not updated at all, a default
+value of 30 is given.
+@end table
+
+@item
+In the first example above, the 9th key is a multi-part key with two parts.
+
+@item Keyblocks used
+What percentage of the keyblocks are used. Because the table used in the
+examples had just been reorganized with @code{myisamchk}, the values are very
+high (very near the theoretical maximum).
+
+@item Packed
+@strong{MySQL} tries to pack keys with a common suffix. This can only be used
+for @code{CHAR}/@code{VARCHAR}/@code{DECIMAL} keys. For long strings like
+names, this can significantly reduce the space used. In the third example
+above, the 4th key is 10 characters long and a 60% reduction in space is
+achieved.
+
+@item Max levels
+How deep the B-tree for this key is. Large tables with long keys get high
+values.
+
+@item Records
+How many rows are in the table.
+
+@item M.recordlength
+The average record length. For tables with fixed-length records, this is the
+exact record length.
+
+@item Packed
+@strong{MySQL} strips spaces from the end of strings. The @code{Packed}
+value indicates the percentage savings achieved by doing this.
+
+@item Recordspace used
+What percentage of the data file is used.
+
+@item Empty space
+What percentage of the data file is unused.
+
+@item Blocks/Record
+Average number of blocks per record (i.e., how many links a fragmented
+record is composed of). This is always 1 for fixed-format tables. This value
+should stay as close to 1.0 as possible. If it gets too big, you can
+reorganize the table with @code{myisamchk}.
+@xref{Optimization}.
+
+@item Recordblocks
+How many blocks (links) are used. For fixed format, this is the same as the number
+of records.
+
+@item Deleteblocks
+How many blocks (links) are deleted.
+
+@item Recorddata
+How many bytes in the data file are used.
+
+@item Deleted data
+How many bytes in the data file are deleted (unused).
+
+@item Lost space
+If a record is updated to a shorter length, some space is lost. This is
+the sum of all such losses, in bytes.
+
+@item Linkdata
+When the dynamic table format is used, record fragments are linked with
+pointers (4 to 7 bytes each). @code{Linkdata} is the sum of the amount of
+storage used by all such pointers.
+@end table
+
+If a table has been compressed with @code{myisampack}, @code{myisamchk
+-d} prints additional information about each table column. See
+@ref{myisampack, , @code{myisampack}}, for an example of this
+information and a description of what it means.
+
+@node Crash recovery, Log files, Table-info, Maintenance
+@section Using @code{myisamchk} for crash recovery
+
+If you run @code{mysqld} with @code{--skip-locking} (which is the default on
+some systems, like Linux), you can't reliably use @code{myisamchk} to
+check a table when @code{mysqld} is using the same table. If you
+can be sure that no one is accessing the tables through @code{mysqld}
+while you run @code{myisamchk}, you only have to do @code{mysqladmin
+flush-tables} before you start checking the tables. If you can't
+guarantee the above, then you must take down @code{mysqld} while you
+check the tables. If you run @code{myisamchk} while @code{mysqld} is updating
+the tables, you may get a warning that a table is corrupt even if it
+isn't.
+
+If you are not using @code{--skip-locking}, you can use @code{myisamchk}
+to check tables at any time. While you do this, all clients that try
+to update the table will wait until @code{myisamchk} is ready before
+continuing.
+
+If you use @code{myisamchk} to repair or optimize tables, you
+@strong{MUST} always ensure that the @code{mysqld} server is not using
+the table (this also applies if you are using @code{--skip-locking}).
+If you don't take down @code{mysqld} you should at least do a
+@code{mysqladmin flush-tables} before you run @code{myisamchk}.
+
+The file format that @strong{MySQL} uses to store data has been extensively
+tested, but there are always external circumstances that may cause database
+tables to become corrupted:
+
+@itemize @bullet
+@item
+The @code{mysqld} process being killed in the middle of a write.
+@item
+Unexpected shutdown of the computer (for example, if the computer is turned
+off).
+@item
+A hardware error.
+@end itemize
+
+This chapter describes how to check for and deal with data corruption
+in @strong{MySQL} databases. If your tables get corrupted a lot you should
+try to find the reason for this! @xref{Debugging server}.
+
+When performing crash recovery, it is important to understand that each table
+@code{tbl_name} in a database corresponds to three files in the database
+directory:
+
+@multitable @columnfractions .2 .8
+@item @strong{File} @tab @strong{Purpose}
+@item @file{tbl_name.frm} @tab Table definition (form) file
+@item @file{tbl_name.MYD} @tab Data file
+@item @file{tbl_name.MYI} @tab Index file
+@end multitable
+
+Each of these three file types is subject to corruption in various ways, but
+problems occur most often in data files and index files.
+
+@code{myisamchk} works by creating a copy of the @file{.MYD} (data) file
+row by row. It ends the repair stage by removing the old @file{.MYD}
+file and renaming the new file to the original file name. If you use
+@code{--quick}, @code{myisamchk} does not create a temporary @file{.MYD}
+file, but instead assumes that the @file{.MYD} file is correct and only
+generates a new index file without touching the @file{.MYD} file. This
+is safe, because @code{myisamchk} automatically detects if the
+@file{.MYD} file is corrupt and aborts the repair in this case. You can
+also give two @code{--quick} options to @code{myisamchk}. In this case,
+@code{myisamchk} does not abort on some errors (like duplicate key) but
+instead tries to resolve them by modifying the @file{.MYD}
+file. Normally the use of two @code{--quick} options is useful only if
+you have too little free disk space to perform a normal repair. In this
+case you should at least make a backup before running @code{myisamchk}.
+
+@menu
+* Check:: How to check tables for errors
+* Repair:: How to repair tables
+* Optimization:: Table optimization
+@end menu
+
+@cindex Checking tables for errors
+@node Check, Repair, Crash recovery, Crash recovery
+@subsection How to check tables for errors
+
+To check a table, use the following commands:
+
+@table @code
+@item myisamchk tbl_name
+This finds 99.99% of all errors. What it can't find is corruption that
+involves @strong{ONLY} the data file (which is very unusual). If you want
+to check a table, you should normally run @code{myisamchk} without options or
+with either the @code{-s} or @code{--silent} option.
+
+@item myisamchk -m tbl_name
+This finds 99.999% of all errors. It checks first all index for errors and
+then it reads through all rows. It calculates a checksum for all keys in
+the rows and verifies that they checksum matches the checksum for the keys
+in the index tree.
+
+@item myisamchk -e tbl_name
+This does a complete and thorough check of all data (@code{-e} means
+``extended check''). It does a check-read of every key for each row to verify
+that they indeed point to the correct row. This may take a LONG time on a
+big table with many keys. @code{myisamchk} will normally stop after the first
+error it finds. If you want to obtain more information, you can add the
+@code{--verbose} (@code{-v}) option. This causes @code{myisamchk} to keep
+going, up through a maximum of 20 errors. In normal usage, a simple
+@code{myisamchk} (with no arguments other than the table name) is sufficient.
+
+@item myisamchk -e -i tbl_name
+Like the previous command, but the @code{-i} option tells @code{myisamchk} to
+print some informational statistics, too.
+@end table
+
+@node Repair, Optimization, Check, Crash recovery
+@subsection How to repair tables
+
+In the following we only talk about using @code{myisamchk} on @code{MyISAM}
+tables (extensions @code{.MYI} and @code{.MYD}). If you are using
+@code{ISAM} tables (extensions @code{.ISM} and @code{.ISD}), you should use
+@code{isamchk} instead.
+
+The symptoms of a corrupted table are usually that queries abort unexpectedly
+and you observe errors such as these:
+
+@itemize @bullet
+@item
+@file{tbl_name.frm} is locked against change
+@item
+Can't find file @file{tbl_name.MYI} (Errcode: ###)
+@item
+Got error ### from table handler (Error 135 is an exception in this case)
+@item
+Unexpected end of file
+@item
+Record file is crashed
+@end itemize
+
+In these cases, you must repair your tables. @code{myisamchk}
+can usually detect and fix most things that go wrong.
+
+The repair process involves up to four stages, described below. Before you
+begin, you should @code{cd} to the database directory and check the
+permissions of the table files. Make sure they are readable by the Unix user
+that @code{mysqld} runs as (and to you, because you need to access the files
+you are checking). If it turns out you need to modify files, they must also
+be writable by you.
+
+If you are using @strong{MySQL} 3.23.16 and above you can (and should) use the
+@code{CHECK} and @code{REPAIR} commands to check and repair @code{MyISAM}
+tables. @xref{CHECK TABLE}. @xref{REPAIR TABLE}.
+
+The manual section about table maintenence includes the options to
+@code{isamchk}/@code{myisamchk}. @xref{Table maintenance}.
+
+The following section is for the cases where the above command fails or
+if you want to use the extended features that isamchk/myisamchk provides.
+
+If you are going to repair a table from the command line, you must first
+take down the @code{mysqld} server. Note that when you do
+@code{mysqladmin shutdown} on a remote server, the @code{mysqld} server
+will still be alive for a while after @code{mysqladmin} returns until
+all queries are stopped and all keys have been flushed to disk.
+
+@noindent
+@strong{Stage 1: Checking your tables}
+
+Run @code{myisamchk *.MYI} or (@code{myisamchk -e *.MYI} if you have
+more time). Use the @code{-s} (silent) option to suppress unnecessary
+information.
+
+If the mysqld server is done you should use the --update option to tell
+@code{myisamchk} to mark the table as 'checked'.
+
+You have to repair only those tables for which @code{myisamchk} announces an
+error. For such tables, proceed to Stage 2.
+
+If you get weird errors when checking (such as @code{out of
+memory} errors), or if @code{myisamchk} crashes, go to Stage 3.
+
+@noindent
+@strong{Stage 2: Easy safe repair}
+
+Note: If you want repairing to go much faster, you should add: @code{-O
+sort_buffer=# -O key_buffer=#} (where # is about 1/4 of the available
+memory) to all @code{isamchk/myisamchk} commands.
+
+First, try @code{myisamchk -r -q tbl_name} (@code{-r -q} means ``quick
+recovery mode''). This will attempt to repair the index file without
+touching the data file. If the data file contains everything that it
+should and the delete links point at the correct locations within the
+data file, this should work, and the table is fixed. Start repairing the
+next table. Otherwise, use the following procedure:
+
+@enumerate
+@item
+Make a backup of the data file before continuing.
+
+@item
+Use @code{myisamchk -r tbl_name} (@code{-r} means ``recovery mode''). This will
+remove incorrect records and deleted records from the data file and
+reconstruct the index file.
+
+@item
+If the preceding step fails, use @code{myisamchk --safe-recover tbl_name}.
+Safe recovery mode uses an old recovery method that handles a few cases that
+regular recovery mode doesn't (but is slower).
+@end enumerate
+
+If you get weird errors when repairing (such as @code{out of
+memory} errors), or if @code{myisamchk} crashes, go to Stage 3.
+
+@noindent
+@strong{Stage 3: Difficult repair}
+
+You should only reach this stage if the first 16K block in the index file is
+destroyed or contains incorrect information, or if the index file is
+missing. In this case, it's necessary to create a new index file. Do so as
+follows:
+
+@enumerate
+@item
+Move the data file to some safe place.
+
+@item
+Use the table description file to create new (empty) data and index files:
+
+@example
+shell> mysql db_name
+mysql> SET AUTOCOMMIT=1;
+mysql> DELETE FROM tbl_name;
+mysql> quit
+@end example
+
+@item
+Copy the old data file back onto the newly created data file.
+(Don't just move the old file back onto the new file; you want to retain
+a copy in case something goes wrong.)
+@end enumerate
+
+Go back to Stage 2. @code{myisamchk -r -q} should work now. (This shouldn't
+be an endless loop).
+
+@noindent
+@strong{Stage 4: Very difficult repair}
+
+You should reach this stage only if the description file has also
+crashed. That should never happen, because the description file isn't changed
+after the table is created.
+
+@enumerate
+@item
+Restore the description file from a backup and go back to Stage 3. You can
+also restore the index file and go back to Stage 2. In the latter case, you
+should start with @code{myisamchk -r}.
+
+@item
+If you don't have a backup but know exactly how the table was created, create
+a copy of the table in another database. Remove the new data file, then move
+the description and index files from the other database to your crashed
+database. This gives you new description and index files, but leaves
+the data file alone. Go back to Stage 2 and attempt to reconstruct
+the index file.
+@end enumerate
+
+@node Optimization, , Repair, Crash recovery
+@subsection Table optimization
+
+To coalesce fragmented records and eliminate wasted space resulting from
+deleting or updating records, run @code{myisamchk} in recovery mode:
+
+@example
+shell> myisamchk -r tbl_name
+@end example
+
+You can optimize a table in the same way using the SQL @code{OPTIMIZE TABLE}
+statement. @code{OPTIMIZE TABLE} is easier, but @code{myisamchk} is faster.
+There is also no possibility of unwanted interaction between a utility
+and the server, because the server does all the work when you use
+@code{OPTIMIZE TABLE}.
+
+@code{myisamchk} also has a number of other options you can use to improve
+the performance of a table:
+
+@table @code
+@item -S, --sort-index
+@item -R index_num, --sort-records=index_num
+@item -a, --analyze
+@end table
+
+For a full description of the option see @xref{myisamchk syntax}.
+
+@node Log files, , Crash recovery, Maintenance
+@section Log file maintenance
+
+When using @strong{MySQL} with log files, you will from time to time
+want to remove/backup old log files and tell @strong{MySQL} to start
+logging on new files. @xref{Update log}.
+
+On a Linux (@code{Redhat}) installation, you can use the
+@code{mysql-log-rotate} script for this. If you installed @strong{MySQL}
+from an RPM distribution, the script should have been installed
+automatically.
+
+On other systems you must install a short script yourself that you
+start from @code{cron} to handle log files.
+
+You can force @strong{MySQL} to start using new log files by using
+@code{mysqladmin flush-logs} or by using the SQL command @code{FLUSH LOGS}.
+If you are using @strong{MySQL} 3.21 you must use @code{mysqladmin refresh}.
+
+The above command does the following:
+
+@itemize @bullet
+@item
+If standard logging (@code{--log}) is used, closes and reopens the log file.
+(@file{mysql.log} as default).
+@item
+If update logging (@code{--log-update}) is used, closes the update log and
+opens a new log file with a higher sequence number.
+@end itemize
+
+If you are using only an update log, you only have to flush the logs and then
+move away the old update log files to a backup.
+If you are using the normal logging, you can do something like:
+
+@example
+shell> cd mysql-data-directory
+shell> mv mysql.log mysql.old
+shell> mysqladmin flush-logs
+@end example
+
+and then take a backup and remove @file{mysql.old}.
+
+@node Adding functions, Adding procedures, Maintenance, Top
+@chapter Adding new functions to MySQL
+
+There are two ways to add new functions to @strong{MySQL}:
+
+@itemize @bullet
+@item You can add the function through the user-definable function (UDF)
+interface. User-definable functions are added and removed dynamically using
+the @code{CREATE FUNCTION} and @code{DROP FUNCTION} statements.
+@xref{CREATE FUNCTION, , @code{CREATE FUNCTION}}.
+
+@item You can add the function as a native (built in) @strong{MySQL} function.
+Native functions are compiled into the @code{mysqld} server and become
+available on a permanent basis.
+@end itemize
+
+Each method has advantages and disadvantages:
+
+@itemize @bullet
+@item
+If you write a user-definable function, you must install the object file
+in addition to the server itself. If you compile your function into the
+server, you don't need to do that.
+@item
+You can add UDFs to a binary @strong{MySQL} distribution. Native functions
+require you to modify a source distribution.
+@item
+If you upgrade your @strong{MySQL} distribution, you can continue to use your
+previously-installed UDFs. For native functions, you must repeat your
+modifications each time you upgrade.
+@end itemize
+
+Whichever method you use to add new functions, they may be used just like
+native functions such as @code{ABS()} or @code{SOUNDEX()}.
+
+@menu
+* Adding UDF:: Adding a new user-definable function
+* Adding native function:: Adding a new native function
+@end menu
+
+@cindex Adding user-definable functions
+@cindex User-definable functions, adding
+@cindex Functions, user-definable, adding
+@node Adding UDF, Adding native function, Adding functions, Adding functions
+@section Adding a new user-definable function
+
+@menu
+* UDF calling sequences:: UDF calling sequences
+* UDF arguments:: Argument processing
+* UDF return values:: Return values and error handling
+* UDF compiling:: Compiling and installing user-definable functions
+@end menu
+
+For the UDF mechanism to work, functions must be written in C or C++ and your
+operating system must support dynamic loading. The @strong{MySQL} source
+distribution includes a file @file{sql/udf_example.cc} that defines 5 new
+functions. Consult this file to see how UDF calling conventions work.
+
+For each function that you want to use in SQL statements, you should define
+corresponding C (or C++) functions. In the discussion below, the name
+``xxx'' is used for an example function name. To distinquish between SQL and
+C/C++ usage, @code{XXX()} (uppercase) indicates a SQL function call, and
+@code{xxx()} (lowercase) indicates a C/C++ function call.
+
+The C/C++ functions that you write to implement the inferface for
+@code{XXX()} are:
+
+@table @asis
+@item @code{xxx()} (required)
+The main function. This is where the function result is computed.
+The correspondence between the SQL type and return type of your C/C++
+function is shown below:
+
+@multitable @columnfractions .2 .8
+@item @strong{SQL type} @tab @strong{C/C++ type}
+@item @code{STRING} @tab @code{char *}
+@item @code{INTEGER} @tab @code{long long}
+@item @code{REAL} @tab @code{double}
+@end multitable
+
+@item @code{xxx_init()} (optional)
+The initialization function for @code{xxx()}. It can be used to:
+
+@itemize @bullet
+@item
+Check the number of arguments to @code{XXX()}.
+@item
+Check that the arguments are of a required type, or, alternatively,
+tell @strong{MySQL} to coerce arguments to the types you want when
+the main function is called.
+@item
+Allocate any memory required by the main function.
+@item
+Specify the maximum length of the result.
+@item
+Specify (for @code{REAL} functions) the maximum number of decimals.
+@item
+Specify whether or not the result can be @code{NULL}.
+@end itemize
+
+@item @code{xxx_deinit()} (optional)
+The deinitialization function for @code{xxx()}. It should deallocate any
+memory allocated by the initialization function.
+@end table
+
+When a SQL statement invokes @code{XXX()}, @strong{MySQL} calls the
+initialization function @code{xxx_init()} to let it perform any required
+setup, such as argument checking or memory allocation. If @code{xxx_init()}
+returns an error, the SQL statement is aborted with an error message and the
+main and deinitialization functions are not called. Otherwise, the main
+function @code{xxx()} is called once for each row. After all rows have been
+processed, the deinitialization function @code{xxx_deinit()} is called so it
+can perform any required cleanup.
+
+All functions must be thread-safe (not just the main function,
+but the initialization and deinitialization functions as well). This means
+that you are not allowed to allocate any global or static variables that
+change! If you need memory, you should allocate it in @code{xxx_init()}
+and free it in @code{xxx_deinit()}.
+
+@node UDF calling sequences, UDF arguments, Adding UDF, Adding UDF
+@subsection UDF calling sequences
+
+The main function should be declared as shown below. Note that the return
+type and parameters differ, depending on whether you will declare the SQL
+function @code{XXX()} to return @code{STRING}, @code{INTEGER} or @code{REAL}
+in the @code{CREATE FUNCTION} statement:
+
+@noindent
+For @code{STRING} functions:
+
+@example
+char *xxx(UDF_INIT *initid, UDF_ARGS *args,
+ char *result, unsigned long *length,
+ char *is_null, char *error);
+@end example
+
+@noindent
+For @code{INTEGER} functions:
+
+@example
+long long xxx(UDF_INIT *initid, UDF_ARGS *args,
+ char *is_null, char *error);
+@end example
+
+@noindent
+For @code{REAL} functions:
+
+@example
+double xxx(UDF_INIT *initid, UDF_ARGS *args,
+ char *is_null, char *error);
+@end example
+
+The initialization and deinitialization functions are declared like this:
+
+@example
+my_bool xxx_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
+
+void xxx_deinit(UDF_INIT *initid);
+@end example
+
+The @code{initid} parameter is passed to all three functions. It points to a
+@code{UDF_INIT} structure that is used to communicate information between
+functions. The @code{UDF_INIT} structure members are listed below. The
+initialization function should fill in any members that it wishes to change.
+(To use the default for a member, leave it unchanged.)
+
+@table @code
+@item my_bool maybe_null
+@code{xxx_init()} should set @code{maybe_null} to @code{1} if @code{xxx()}
+can return @code{NULL}. The default value is @code{1} if any of the
+arguments are declared @code{maybe_null}.
+
+@item unsigned int decimals
+Number of decimals. The default value is the maximum number of decimals in
+the arguments passed to the main function. (For example, if the function is
+passed @code{1.34}, @code{1.345} and @code{1.3}, the default would be 3,
+because @code{1.345} has 3 decimals.
+
+@item unsigned int max_length
+The maximum length of the string result. The default value differs depending
+on the result type of the function. For string functions, the default is the
+length of the longest argument. For integer functions, the default is 21
+digits. For real functions, the default is 13 plus the number of decimals
+indicated by @code{initid->decimals}. (For numeric functions, the length
+includes any sign or decimal point characters.)
+
+@item char *ptr
+A pointer that the function can use for its own purposes. For example,
+functions can use @code{initid->ptr} to communicate allocated memory
+between functions. In @code{xxx_init()}, allocate the memory and assign it
+to this pointer:
+
+@example
+initid->ptr = allocated_memory;
+@end example
+
+In @code{xxx()} and @code{xxx_deinit()}, refer to @code{initid->ptr} to use
+or deallocate the memory.
+@end table
+
+@node UDF arguments, UDF return values, UDF calling sequences, Adding UDF
+@subsection Argument processing
+
+The @code{args} parameter points to a @code{UDF_ARGS} structure which has the
+members listed below:
+
+@table @code
+@item unsigned int arg_count
+The number of arguments. Check this value in the initialization function
+if you want your function to be called with a particular number of arguments.
+For example:
+
+@example
+if (args->arg_count != 2)
+@{
+ strcpy(message,"XXX() requires two arguments");
+ return 1;
+@}
+@end example
+
+
+@item enum Item_result *arg_type
+The types for each argument. The possible type values are
+@code{STRING_RESULT}, @code{INT_RESULT} and @code{REAL_RESULT}.
+
+To make sure that arguments are of a given type and return an
+error if they are not, check the @code{arg_type} array in the initialization
+function. For example:
+
+@example
+if (args->arg_type[0] != STRING_RESULT ||
+ args->arg_type[1] != INT_RESULT)
+@{
+ strcpy(message,"XXX() requires a string and an integer");
+ return 1;
+@}
+@end example
+
+As an alternative to requiring your function's arguments to be of particular
+types, you can use the initialization function to set the @code{arg_type}
+elements to the types you want. This causes @strong{MySQL} to coerce
+arguments to those types for each call to @code{xxx()}. For example, to
+specify coercion of the first two arguments to string and integer, do this in
+@code{xxx_init()}:
+
+@example
+args->arg_type[0] = STRING_RESULT;
+args->arg_type[1] = INT_RESULT;
+@end example
+
+@item char **args
+@code{args->args} communicates information to the initialization function
+about the general nature of the arguments your function was called with. For a
+constant argument @code{i}, @code{args->args[i]} points to the argument
+value. (See below for instructions on how to access the value properly.)
+For a non-constant argument, @code{args->args[i]} is @code{0}.
+A constant argument is an expression that uses only constants, such as
+@code{3} or @code{4*7-2} or @code{SIN(3.14)}. A non-constant argument is an
+expression that refers to values that may change from row to row, such as
+column names or functions that are called with non-constant arguments.
+
+For each invocation of the main function, @code{args->args} contains the
+actual arguments that are passed for the row currently being processed.
+
+Functions can refer to an argument @code{i} as follows:
+
+@itemize @bullet
+@item
+An argument of type @code{STRING_RESULT} is given as a string pointer plus a
+length, to allow handling of binary data or data of arbitrary length. The
+string contents are available as @code{args->args[i]} and the string length
+is @code{args->lengths[i]}. You should not assume that strings are
+null-terminated.
+
+@item
+For an argument of type @code{INT_RESULT}, you must cast
+@code{args->args[i]} to a @code{long long} value:
+
+@example
+long long int_val;
+int_val = *((long long*) args->args[i]);
+@end example
+
+@item
+For an argument of type @code{REAL_RESULT}, you must cast
+@code{args->args[i]} to a @code{double} value:
+
+@example
+double real_val;
+real_val = *((double*) args->args[i]);
+@end example
+@end itemize
+
+@item unsigned long *lengths
+For the initialization function, the @code{lengths} array indicates the
+maximum string length for each argument. For each invocation of the main
+function, @code{lengths} contains the actual lengths of any string arguments
+that are passed for the row currently being processed. For arguments of
+types @code{INT_RESULT} or @code{REAL_RESULT}, @code{lengths} still contains
+the maximum length of the argument (as for the initialization function).
+@end table
+
+@node UDF return values, UDF compiling, UDF arguments, Adding UDF
+@subsection Return values and error handling
+
+The initialization function should return @code{0} if no error occurred and
+@code{1} otherwise. If an error occurs, @code{xxx_init()} should store a
+null-terminated error message in the @code{message} parameter. The message
+will be returned to the client. The message buffer is
+@code{MYSQL_ERRMSG_SIZE} characters long, but you should try to keep the
+message to less than 80 characters so that it fits the width of a standard
+terminal screen.
+
+The return value of the main function @code{xxx()} is the function value, for
+@code{long long} and @code{double} functions. For string functions, the
+string is returned in the @code{result} and @code{length} arguments.
+@code{result} is a buffer at least 255 bytes long. Set these to the contents
+and length of the return value. For example:
+
+@example
+memcpy(result, "result string", 13);
+*length = 13;
+@end example
+
+The string function return value normally also points to the result.
+
+To indicate a return value of @code{NULL} in the main function, set
+@code{is_null} to @code{1}:
+
+@example
+*is_null = 1;
+@end example
+
+To indicate an error return in the main function, set the @code{error}
+parameter to @code{1}:
+
+@example
+*error = 1;
+@end example
+
+If @code{xxx()} sets @code{*error} to @code{1} for any row, the function
+value is @code{NULL} for the current row and for any subsequent rows
+processed by the statement in which @code{XXX()} was invoked. (@code{xxx()}
+will not even be called for subsequent rows.) @strong{Note:} In
+@strong{MySQL} versions prior to 3.22.10, you should set both @code{*error}
+and @code{*is_null}:
+
+@example
+*error = 1;
+*is_null = 1;
+@end example
+
+@node UDF compiling, , UDF return values, Adding UDF
+@subsection Compiling and installing user-definable functions
+
+Files implementing UDFs must be compiled and installed on the host where the
+server runs. This process is described below for the example UDF file
+@file{udf_example.cc} that is included in the @strong{MySQL} source
+distribution. This file contains the following functions:
+
+@itemize @bullet
+@item
+@code{metaphon()} returns a metaphon string of the string argument.
+This is something like a soundex string, but it's more tuned for English.
+@item
+@code{myfunc_double()} returns the sum of the ASCII values of the
+characters in its arguments, divided by the sum of the length of its arguments.
+@item
+@code{myfunc_int()} returns the sum of the length of its arguments.
+@item
+@code{lookup()} returns the IP number for a hostname.
+@item
+@code{reverse_lookup()} returns the hostname for an IP number.
+The function may be called with a string @code{"xxx.xxx.xxx.xxx"} or
+four numbers.
+@end itemize
+
+A dynamically-loadable file should be compiled as a sharable object file,
+using a command something like this:
+
+@example
+shell> gcc -shared -o udf_example.so myfunc.cc
+@end example
+
+You can easily find out the correct compiler options for your system by
+running this command in the @file{sql} directory of your @strong{MySQL}
+source tree:
+
+@example
+shell> make udf_example.o
+@end example
+
+You should run a compile command similar to the one that @code{make} displays,
+except that you should remove the @code{-c} option near the end of the line
+and add @code{-o udf_example.so} to the end of the line. (On some systems,
+you may need to leave the @code{-c} on the command.)
+
+Once you compile a shared object containing UDFs, you must install it
+and tell @strong{MySQL} about it. Compiling a shared object from
+@file{udf_example.cc} produces a file named something like
+@file{udf_example.so} (the exact name may vary from platform to platform).
+Copy this file to some directory searched by @code{ld}, such as
+@file{/usr/lib}. On many systems, you can set the @code{LD_LIBRARY} or
+@code{LD_LIBRARY_PATH} environment variable to point at the directory where
+you have your UDF function files. The @code{dlopen} manual page tells you
+which variable you should use on your system. You should set this in
+@code{mysql.server} or @code{safe_mysqld} and restart @code{mysqld}.
+
+After the library is installed, notify @code{mysqld} about the new
+functions with these commands:
+
+@example
+mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME "udf_example.so";
+mysql> CREATE FUNCTION myfunc_double RETURNS REAL SONAME "udf_example.so";
+mysql> CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "udf_example.so";
+mysql> CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so";
+mysql> CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "udf_example.so";
+@end example
+
+Functions can be deleted using @code{DROP FUNCTION}:
+
+@example
+mysql> DROP FUNCTION metaphon;
+mysql> DROP FUNCTION myfunc_double;
+mysql> DROP FUNCTION myfunc_int;
+mysql> DROP FUNCTION lookup;
+mysql> DROP FUNCTION reverse_lookup;
+@end example
+
+The @code{CREATE FUNCTION} and @code{DROP FUNCTION} statements update the
+system table @code{func} in the @code{mysql} database. The function's name,
+type and shared library name are saved in the table. You must have the
+@strong{insert} and @strong{delete} privileges for the @code{mysql} database
+to create and drop functions.
+
+You should not use @code{CREATE FUNCTION} to add a function that has already
+been created. If you need to reinstall a function, you should remove it with
+@code{DROP FUNCTION} and then reinstall it with @code{CREATE FUNCTION}. You
+would need to do this, for example, if you recompile a new version of your
+function, so that @code{mysqld} gets the new version. Otherwise the server
+will continue to use the old version.
+
+Active functions are reloaded each time the server starts, unless you start
+@code{mysqld} with the @code{--skip-grant-tables} option. In this case, UDF
+initialization is skipped and UDFs are unavailable. (An active function is
+one that has been loaded with @code{CREATE FUNCTION} and not removed with
+@code{DROP FUNCTION}.)
+
+@cindex Adding native functions
+@cindex Native functions, adding
+@cindex Functions, native, adding
+@node Adding native function, , Adding UDF, Adding functions
+@section Adding a new native function
+
+The procedure for adding a new native function is described below. Note that
+you cannot add native functions to a binary distribution because the procedure
+involves modifying @strong{MySQL} source code. You must compile
+@strong{MySQL} yourself from a source distribution. Also note that if you
+migrate to another version of @strong{MySQL} (e.g., when a new version is
+released), you will need to repeat the procedure with the new version.
+
+To add a new native @strong{MySQL} function, follow these steps:
+
+@enumerate
+@item
+Add one line to @file{lex.h} that defines the function name in the
+@code{sql_functions[]} array.
+@item
+Add two lines to @file{sql_yacc.yy}. One indicates the preprocessor
+symbol that @code{yacc} should define (this should be added at the
+beginning of the file). Then define the function parameters and add an
+``item'' with these parameters to the @code{simple_expr} parsing rule.
+For an example, check all occurrences of @code{SOUNDEX} in
+@file{sql_yacc.yy} to see how this is done.
+@item
+In @file{item_func.h}, declare a class inheriting from @code{Item_num_func} or
+@code{Item_str_func}, depending on whether your function returns a number or a
+string.
+@item
+In @file{item_func.cc}, add one of the following declarations, depending
+on whether you are defining a numeric or string function:
+@example
+double Item_func_newname::val()
+longlong Item_func_newname::val_int()
+String *Item_func_newname::Str(String *str)
+@end example
+@item
+You should probably also define the following function:
+@example
+void Item_func_newname::fix_length_and_dec()
+@end example
+This function should at least calculate @code{max_length} based on the
+given arguments. @code{max_length} is the maximum number of characters
+the function may return. This function should also set @code{maybe_null = 0}
+if the main function can't return a @code{NULL} value. The function can check
+if any of the function arguments can return @code{NULL} by checking the
+arguments @code{maybe_null} variable.
+@end enumerate
+
+All functions must be thread-safe.
+
+For string functions, there are some additional considerations to be aware of:
+@itemize @bullet
+@item
+The @code{String *str} argument provides a string
+buffer that may be used to hold the result.
+@item
+The function should return the string that holds the result.
+@item
+All current string functions try to avoid allocating any memory unless
+absolutely necessary!
+@end itemize
+
+@node Adding procedures, ODBC, Adding functions, Top
+@chapter Adding new procedures to MySQL
+
+In @strong{MySQL}, you can define a procedure in C++ that can access and
+modify the data in a query before it is sent to the client. The modification
+can be done on row by row or @code{GROUP BY} level.
+
+We have created an example procedure in @strong{MySQL} 3.23 to
+show you what can be done.
+
+@menu
+* procedure analyse:: Procedure analyse
+* Writing a procedure:: Writing a procedure.
+@end menu
+
+@node procedure analyse, Writing a procedure, Adding procedures, Adding procedures
+@section Procedure analyse
+
+@code{analyse([max elements,[max memory]])}
+
+This procedure is defined in the @file{sql/sql_analyse.cc}. This
+examines the result from your query and returns an analysis of the
+results.
+
+@itemize @bullet
+@item
+@code{max elements} (default 256) is the maximum number of distinct values
+@code{analyse} will notice per column. This is used by @code{analyse} to check if
+the optimal column type should be of type @code{ENUM}.
+@item
+@code{max memory} (default 8192) is the maximum memory @code{analyse} should
+allocate per column while trying to find all distinct values.
+@end itemize
+
+@example
+SELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max elements,[max memory]])
+@end example
+
+@node Writing a procedure, , procedure analyse, Adding procedures
+@section Writing a procedure.
+
+For the moment, the only documentation for this is the source. :(
+
+You can find all information about procedures by examining the following files:
+
+@itemize @bullet
+@item @file{sql/sql_analyse.cc}
+@item @file{sql/procedure.h}
+@item @file{sql/procedure.cc}
+@item @file{sql/sql_select.cc}
+@end itemize
+
+@cindex ODBC
+@cindex Windows
+@cindex MyODBC
+@node ODBC, Common programs, Adding procedures, Top
+@chapter MySQL ODBC Support
+
+@menu
+* Which ODBC OS:: Operating systems supported by @strong{MyODBC}
+* ODBC administrator:: How to fill in the various fields in the ODBC administrator program
+* ODBC Problems:: How to report problems with @strong{MySQL} ODBC
+* MyODBC clients:: Programs known to work with @strong{MyODBC}
+* ODBC and last_insert_id:: How to get the value of an @code{AUTO_INCREMENT} column in ODBC
+* MyODBC bug report:: Reporting problems with MyODBC
+@end menu
+
+@strong{MySQL} provides support for ODBC by means of the @strong{MyODBC}
+program.
+
+@node Which ODBC OS, ODBC administrator, ODBC, ODBC
+@section Operating systems supported by MyODBC
+
+@strong{MyODBC} is a 32-bit ODBC (2.50) level 0 driver for connecting
+an ODBC-aware application to @strong{MySQL}. @strong{MyODBC} works on
+Windows95, Windows98, NT and on most Unix platforms.
+
+Normally you only need to install @strong{MyODBC} on Windows machines.
+You only need @strong{MyODBC} for Unix if you have a program like
+ColdFusion that is running on the Unix machine and uses ODBC to connect
+to the databases.
+
+@strong{MyODBC} is in public domain and you can find the newest version
+at @uref{http://www.mysql.com/downloads/api-myodbc.html}.
+
+If you want to install @strong{MyODBC} on a Unix box, you will also need
+an @strong{ODBC} manager. @strong{MyODBC} is known to work with
+most of the Unix ODBC managers. You can find a list at these in the
+@strong{ODBC}-related links section on the @strong{MySQL} useful links page.
+@xref{Useful Links}.
+
+On Windows/NT you may get the following error when trying to install
+@strong{MyODBC}:
+
+@example
+An error occurred while copying C:\WINDOWS\SYSTEM\MFC30.DLL. Restart Windows
+and try installing again (before running any applications which use ODBC)
+@end example
+
+The problem in this case is that some other program is using ODBC and
+because of how windows is designed, you cannot in this case install new
+ODBC drivers with Microsoft's ODBC setup program. :( The solution to this
+is to reboot your computer in ``safe mode`` (You can choose this by
+pressing F8 just before your machine starts Windows during rebooting),
+install @strong{MyODBC} and reboot to normal mode.
+
+@itemize @bullet
+@item
+To make a connection to an Unix box from a Windows box, with an ODBC
+application (one that doesn't support @strong{MySQL} natively), you must
+first install @strong{MyODBC} on the Windows machine.
+@item
+The user and Windows machine must have the access privileges to the
+@strong{MySQL} server the Unix machine. This is set up with the @code{GRANT}
+command. @xref{GRANT,,@code{GRANT}}.
+@item
+You must create an ODBC DSN entry as follows:
+
+@itemize @bullet
+@item
+Open the Control Panel on the Windows machine.
+@item
+Double click the ODBC Data Sources 32 bits icon.
+@item
+Click the tab User DSN.
+@item
+Click the button Add.
+@item
+Select @strong{MySQL} in the screen Create New Data Source and click
+the Finish button.
+@item
+The @strong{MySQL} Driver default configuration screen is shown.
+@xref{ODBC administrator}.
+@end itemize
+
+@item
+Now start your application and select the ODBC driver with the DSN you
+specified in the ODBC administrator.
+@end itemize
+
+Notice that there are other configuration options in the screen of
+@strong{MySQL} (trace, don't prompt on connect, etc) that you can try if
+you run into problems.
+
+@node ODBC administrator, ODBC Problems, Which ODBC OS, ODBC
+@section How to fill in the various fields in the ODBC administrator program
+
+There are three possibilities for specifying the server name on
+Windows95:
+
+@itemize @bullet
+@item
+Use the IP address of the server.
+@item
+Add a file @file{\windows\lmhosts} with the following information:
+
+@example
+ip hostname
+@end example
+
+For example:
+
+@example
+194.216.84.21 my_hostname
+@end example
+
+@item
+Configure the PC to use DNS.
+@end itemize
+
+Example of how to fill in the @code{ODBC setup}
+@example
+Windows DSN name: test
+Description: This is my test database
+MySql Database: test
+Server: 194.216.84.21
+User: monty
+Password: my_password
+Port:
+@end example
+
+The value for the @code{Windows DSN name} field is any name that is unique
+in your Windows ODBC setup.
+
+You don't have to specify values for the @code{Server}, @code{User},
+@code{Password} or @code{Port} fields in the ODBC setup screen.
+However, if you do, the values will be used as the defaults later when
+you attempt to make a connection. You have the option of changing the
+values at that time.
+
+If the port number is not given, the default port (@value{default_port})
+is used.
+
+If you specify the option @code{Read options from C:\my.cnf}, the groups
+@code{client} and @code{odbc} will be read from the @file{C:\my.cnf} file.
+You can use all options that are usable by @code{mysql_options()}.
+@xref{mysql_options, , @code{mysql_options}}.
+
+@node ODBC Problems, MyODBC clients, ODBC administrator, ODBC
+@section How to report problems with MyODBC
+
+@strong{MyODBC} has been tested with Access, Admndemo.exe, C++-Builder,
+Borland Builder 4, Centura Team Developer (formerly Gupta SQL/Windows),
+ColdFusion (on Solaris and NT with svc pack 5), Crystal Reports,
+DataJunction, Delphi, ERwin, Excel, iHTML, FileMaker Pro, FoxPro, Notes
+4.5/4.6, SBSS, Perl DBD-ODBC, Paradox, Powerbuilder, Powerdesigner 32
+bit, VC++ and Visual Basic.
+
+If you know of any other applications that work with @strong{MyODBC}, please
+mail @email{myodbc@@lists.mysql.com} about this!
+
+With some programs you may get an error like:
+@code{Another user has modifies the record that you have modified}. In most
+cases this can be solved by doing one of the following things:
+
+@itemize @bullet
+@item
+Add a primary key for the table if there isn't one already.
+@item
+Add a timestamp column if there isn't one already.
+@item
+Only use double float fields. Some programs may fails when they comparing
+single floats.
+@end itemize
+
+If the above doesn't help, you should do a @code{MyODBC} trace file and
+from this try to figure out why things goes wrong.
+
+@node MyODBC clients, ODBC and last_insert_id, ODBC Problems, ODBC
+@section Programs known to work with MyODBC
+
+Most programs should work with @strong{MyODBC}, but for each of those
+listed below, we have tested it ourselves or gotten confirmation from
+some user that it works:
+
+@table @asis
+@item @strong{Program}
+@strong{Comment}
+@item Access
+To make Access work:
+@itemize @bullet
+@item
+You should have a primary key in the table.
+@item
+You should have a timestamp in all tables you want to be able to update.
+@item
+Only use double float fields. Access fails when comparing with single floats.
+@item
+Set the `Return matching rows' option field when connecting to @strong{MySQL}.
+@item
+Access on NT will report @code{BLOB} columns as @code{OLE OBJECTS}. If
+you want to have @code{MEMO} columns instead, you should change the
+column to @code{TEXT} with @code{ALTER TABLE}.
+@item
+Access can't always handle @code{DATE} columns properly. If you have a problem
+with these, change the columns to @code{DATETIME}.
+@item
+In some cases, Access may generate illegal SQL queries that
+@strong{MySQL} can't understand. You can fix this by selecting
+@code{"Query|SQLSpecific|Pass-Through"} from the Access menu.
+
+@end itemize
+@item Borland Builder 4
+When you start a query you can use the property @code{Active} or use the
+method @code{Open}. Note that @code{Active} will start by automatically issue
+a @code{SELECT * FROM ...} query that may not be a good thing if your tables
+are big!
+@item ColdFusion (On Unix)
+The following information is taken from the ColdFusion documentation:
+
+Use the following information to configure ColdFusion Server for Linux
+to use the unixODBC driver with @strong{MyODBC} for @strong{MySQL} data
+sources. Allaire has verified that @strong{MyODBC} version 2.50.26
+works with @strong{MySQL} version 3.22.27 and ColdFusion for Linux. (Any
+newer version should also work). You can download @strong{MyODBC} at
+@uref{http://www.mysql.com/downloads/api-myodbc.html}
+
+ColdFusion 4.5.1 allows you to us the ColdFusion Administrator to add
+the @strong{MySQL} data source. However, the driver is not included with
+ColdFusion 4.5.1. Before the @strong{MySQL} driver will appear in the ODBC
+datasources drop-down list, you must build and copy the @strong{MyODBC} driver
+to @file{/opt/coldfusion/lib/libmyodbc.so}.
+
+@item DataJunction
+You have to change it to output @code{VARCHAR} rather than @code{ENUM}, as
+it exports the latter in a manner that causes @strong{MySQL} grief.
+@item Excel
+Works. Some tips:
+@itemize @bullet
+@item
+If you have problems with dates, try to select them as strings using the
+@code{CONCAT()} function. For example:
+@example
+select CONCAT(rise_time), CONCAT(set_time)
+ from sunrise_sunset;
+@end example
+Values retrieved as strings this way should be correctly recognized
+as time values by Excel97.
+
+The purpose of @code{CONCAT()} in this example is to fool ODBC into thinking
+the column is of ``string type''. Without the @code{CONCAT()}, ODBC knows the
+column is of time type, and Excel does not understand that.
+
+Note that this is a bug in Excel, because it automatically converts a
+string to a time. This would be great if the source was a text file, but
+is plain stupid when the source is an ODBC connection that reports
+exact types for each column.
+@end itemize
+@item odbcadmin
+Test program for ODBC.
+@item Delphi
+You must use DBE 3.2 or newer. Set the `Don't optimize column width'
+option field when connecting to @strong{MySQL}.
+
+Also, here is some potentially useful Delphi code that sets up both an
+ODBC entry and a BDE entry for @strong{MyODBC} (the BDE entry requires a BDE
+Alias Editor which may be had for free at a Delphi Super Page near
+you.): (Thanks to Bryan Brunton @email{bryan@@flesherfab.com} for this)
+
+@example
+fReg:= TRegistry.Create;
+ fReg.OpenKey('\Software\ODBC\ODBC.INI\DocumentsFab', True);
+ fReg.WriteString('Database', 'Documents');
+ fReg.WriteString('Description', ' ');
+ fReg.WriteString('Driver', 'C:\WINNT\System32\myodbc.dll');
+ fReg.WriteString('Flag', '1');
+ fReg.WriteString('Password', '');
+ fReg.WriteString('Port', ' ');
+ fReg.WriteString('Server', 'xmark');
+ fReg.WriteString('User', 'winuser');
+ fReg.OpenKey('\Software\ODBC\ODBC.INI\ODBC Data Sources', True);
+ fReg.WriteString('DocumentsFab', 'MySQL');
+ fReg.CloseKey;
+ fReg.Free;
+
+ Memo1.Lines.Add('DATABASE NAME=');
+ Memo1.Lines.Add('USER NAME=');
+ Memo1.Lines.Add('ODBC DSN=DocumentsFab');
+ Memo1.Lines.Add('OPEN MODE=READ/WRITE');
+ Memo1.Lines.Add('BATCH COUNT=200');
+ Memo1.Lines.Add('LANGDRIVER=');
+ Memo1.Lines.Add('MAX ROWS=-1');
+ Memo1.Lines.Add('SCHEMA CACHE DIR=');
+ Memo1.Lines.Add('SCHEMA CACHE SIZE=8');
+ Memo1.Lines.Add('SCHEMA CACHE TIME=-1');
+ Memo1.Lines.Add('SQLPASSTHRU MODE=SHARED AUTOCOMMIT');
+ Memo1.Lines.Add('SQLQRYMODE=');
+ Memo1.Lines.Add('ENABLE SCHEMA CACHE=FALSE');
+ Memo1.Lines.Add('ENABLE BCD=FALSE');
+ Memo1.Lines.Add('ROWSET SIZE=20');
+ Memo1.Lines.Add('BLOBS TO CACHE=64');
+ Memo1.Lines.Add('BLOB SIZE=32');
+
+ AliasEditor.Add('DocumentsFab','MySQL',Memo1.Lines);
+@end example
+
+@item 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 recognize primary keys, only the index PRIMARY, though this has not
+been a problem.
+@item Visual Basic
+To be able to update a table, you must define a primary key for the table.
+
+Visual Basic with ADO can't handle big integers; This means that some queries
+like @code{SHOW PROCESSLIST} will not work properly. The fix is to set
+add the option @code{OPTION=16834} in the ODBC connect string or set
+the @code{Change BIGINT columns to INT} option in the MyODBC connect screen.
+@end table
+
+@node ODBC and last_insert_id, MyODBC bug report, MyODBC clients, ODBC
+@section How to get the value of an @code{AUTO_INCREMENT} column in ODBC
+
+A common problem is how to get the value of an automatically generated ID
+from an @code{INSERT}. With ODBC, you can do something like this (assuming
+that @code{auto} is an @code{AUTO_INCREMENT} field):
+
+@example
+INSERT INTO foo (auto,text) VALUES(NULL,'text');
+SELECT LAST_INSERT_ID();
+@end example
+
+Or, if you are just going to insert the ID into another table, you can do this:
+
+@example
+INSERT INTO foo (auto,text) VALUES(NULL,'text');
+INSERT INTO foo2 (id,text) VALUES(LAST_INSERT_ID(),'text');
+@end example
+
+For the benefit of some ODBC applications (at least Delphi and Access),
+the following query can be used to find a newly-inserted row:
+@example
+SELECT * FROM tbl_name WHERE auto IS NULL;
+@end example
+
+@node MyODBC bug report, , ODBC and last_insert_id, ODBC
+@section Reporting problems with MyODBC
+
+If you encounter difficulties with @strong{MyODBC}, you should start by
+making a log file from the ODBC manager (the log you get when requesting
+logs from ODBCADMIN) and a @strong{MyODBC} log. To get a @strong{MyODBC}
+log, tag the `Trace MyODBC' option flag in the @strong{MyODBC}
+connect/configure screen. The log will be written to file
+@file{C:\myodbc.log}. Note that you must use @code{MYSQL.DLL} and not
+@code{MYSQL2.DLL} for this option to work!
+
+Check the queries that MyODBC sends to the @strong{MySQL} server; You
+should be able to find this by searching after the string
+@code{>mysql_real_query} in the @file{myodbc.log} file.
+
+You should also try duplicating the queries in the @code{mysql} monitor
+or @code{admndemo} to find out if the error is MyODBC or @strong{MySQL}.
+
+If you find out something is wrong, please only send the relevant rows
+(max 40 rows) to the @email{myodbc@@lists.mysql.com}. Please never
+send the whole MyODBC or ODBC log file!
+
+If you are unable to find out what's wrong, the last option is to to
+make an archive (tar or zip) that contains a MyODBC log file, the ODBC
+log file and a README file that explains the problem. You can send this
+to @uref{ftp://support.mysql.com/pub/mysql/secret}. Only we at MySQL AB
+will have access to the files you upload and we will be very discrete
+with the data!
+
+If you can create a program that also shows this problem, please
+upload this too!
+
+If the program works with some other SQL server, you should make an ODBC log
+file where you do exactly the same thing in the other SQL server.
+
+Remember that the more information you can supply to us, the more
+likely it is that we can fix the problem!
+
+@node Common programs, Problems, ODBC, Top
+@chapter Using @code{MySQL} with some common programs
+
+@menu
+* Apache:: Using @strong{MySQL} with Apache
+@end menu
+
+@node Apache, , Common programs, Common programs
+@section Using MySQL with Apache
+
+The contrib section includes programs that let you authenticate your
+users from a @strong{MySQL} database and also let you log your log files
+into a @strong{MySQL} table. @xref{Contrib}.
+
+You can change the Apache logging format to be easily readable by
+@code{MySQL} by putting the following into the Apache configuration file:
+
+@example
+LogFormat \
+ "\"%h\",%@{%Y%m%d%H%M%S@}t,%>s,\"%b\",\"%@{Content-Type@}o\", \
+ \"%U\",\"%@{Referer@}i\",\"%@{User-Agent@}i\""
+@end example
+
+In @strong{MySQL} you can do something like this:
+
+@example
+LOAD DATA INFILE '/local/access_log' INTO TABLE table_name
+FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'
+@end example
+
+@node Problems, Common problems, Common programs, Top
+@chapter Problems and common errors
+
+@menu
+* What is crashing:: How to determinate what is causing problems
+* Crashing:: What to do if @strong{MySQL} keeps crashing
+* Link errors:: Problems when linking with the @strong{MySQL} client library
+* Common errors:: Some common errors when using @strong{MySQL}
+* Full disk:: How @strong{MySQL} handles a full disk
+* Multiple sql commands:: How to run SQL commands from a text file
+* Temporary files:: Where @strong{MySQL} stores temporary files
+* Problems with mysql.sock:: How to protect @file{/tmp/mysql.sock}
+* Error Access denied:: @code{Access denied} error
+* Changing MySQL user :: How to run @strong{MySQL} as a normal user
+* Resetting permissions:: How to reset a forgotten password.
+* File permissions :: Problems with file permissions
+* Not enough file handles:: File not found
+* Using DATE:: Problems using @code{DATE} columns
+* Timezone problems:: Timezone problems
+* Case sensitivity:: Case sensitivity in searches
+* Problems with NULL:: Problems with @code{NULL} values
+* Problems with alias:: Problems with @code{alias}
+* Deleting from related tables:: Deleting rows from related tables
+* No matching rows:: Solving problems with no matching rows
+* ALTER TABLE problems:: Problems with @code{ALTER TABLE}.
+* Change column order:: How to change the order of columns in a table
+@end menu
+
+@node What is crashing, Crashing, Problems, Problems
+@section How to determinate what is causing problems
+
+When you run into problems, the first thing you should do is to find out
+which program / piece of equipment is causing problems.
+
+@itemize @bullet
+@item
+If you have one of the following symptoms, then it is probably a hardware
+(like memory, motherboard, CPU, or harddisk) or kernel problem:
+@itemize @bullet
+@item
+The keyboard doesn't work. This can normally be checked by pressing
+Caps Lock; If the Caps Lock light doesn't change you have to replace
+your keyboard. (Before doing this, you should however try to reboot
+your computer and check all cables to the keyboard :)
+@item
+The mouse pointer doesn't move.
+@item
+The machine doesn't answer to a remote machine's pings.
+@item
+Different, unrelated programs don't behave correctly.
+@item
+If your system rebooted unexpectedly (a faulty user level program should
+NEVER be able to take down your system).
+@end itemize
+
+In this case you should start by checking all your cables and run some
+diagnostic tool to check your hardware!
+You should also check if there are any patches, updates or service
+packs for your operating system that could likely solve your problems.
+Check also that all your libraries (like glibc) are up to date.
+
+It's always good to use a machine with ECC memory to discover
+memory problems early!
+@item
+If your keyboard is locked up, you may be able to fix this by
+logging into your machine from another machine and execute
+@code{kbd_mode -a} on it.
+
+@item
+Please examine your system log file, (/var/log/messages or similar) for
+reasons for your problems. If you think the problem is in @strong{MySQL}
+then you should also examine @strong{MySQL}'s log files. @xref{Update log}.
+
+@item
+If you don't think you have hardware problems, you should try to find
+out which program is causing problems.
+
+Try using @code{top}, @code{ps}, @code{taskmanager} or some similar program,
+to check which program is taking all CPU, or is locking the machine.
+
+@item
+Check with @code{top}, @code{df} or a similar programs if you are out of
+memory, disk space, open files or some other critical resource.
+
+@item
+If the problem is some runaway process, you can always try to kill if. If it
+doesn't want to die, this is probably a bug in the operating system.
+@end itemize
+
+If after you have examined all other possibilities and you have
+concluded that its the @strong{MySQL} server or a @strong{MySQL} client
+that is causing the problem, it's time to do a bug report for our
+mailing list or our support team. In the bug report, try to describe
+very detailed how the system is behaving and what you think is
+happening. You should also state why you think it's @strong{MySQL} that
+is causing the problems. Take in consideration all the situations in
+this chapter. State any problems exactly how they appear when you
+examine your system.. Use the 'cut and paste' method for any output
+and/or error messages from programs and/or log files!
+
+Try to describe very detailed which program is not working and all
+symptoms you see! We have in the past got many bug reports that just
+states "the system doesn't work". This doesn't provide us with any
+information of what could be the problem.
+
+If a program fails, it's always useful to know:
+
+@itemize @bullet
+@item
+Has the program in question made a segmentation fault (core dumped)?
+@item
+Is the program taking the whole CPU? Check with @code{top}. Let the
+program run for a while, it may be evaluating something heavy.
+@item
+If it's the @code{mysqld} server that is causing problems; Can you
+do @code{mysqladmin -u root ping}, or @code{mysqladmin -u root processlist}?
+@item
+What does a client program say (try with @code{mysql} for example)
+when you try to connect to the @strong{MySQL} server?
+Does the client jam? Do you get any output from the program?
+@end itemize
+
+When send a bug report, you should of course follow the outlines
+described in this manual. @xref{Asking questions}.
+
+@node Crashing, Link errors, What is crashing, Problems
+@section What to do if MySQL keeps crashing
+
+All @strong{MySQL} versions are tested on many platforms before they are
+released. This doesn't mean that there isn't any bugs in
+@strong{MySQL}, but that if there are bugs they are very few and can be
+hard to find. If you have a problem, it will always help if you try to
+find out exactly what crashes your system as you will have a much better
+chance of getting this fixed quickly.
+
+First you should try to find out whether the problem is that the
+@code{mysqld} daemon dies or whether your problem has to do with your
+client. You can check how long your @code{mysqld} server has been up by
+executing @code{mysqladmin version}. If @code{mysqld} has died, you may
+find the reason for this in the file
+@file{mysql-data-directory/'hostname'.err}.
+
+Many crashes of @strong{MySQL} is caused by corrupted index / data
+files. @strong{MySQL} will update the data on disk, with the
+@code{write()} system call, after every SQL statement and before the
+client is notified about the result (this is not true if you are running
+with @code{delayed_key_writes}, in which case only the data is written).
+This means that the data is safe even if mysqld crashes as the OS will
+ensure that the not flushed data is written to disk. You can force
+@strong{MySQL} to sync everything to disk after every SQL command by
+starting @code{mysqld} with @code{--flush}.
+
+The above means that normally you shouldn't get corrupted tables unless:
+
+@itemize @bullet
+@item
+Someone/something killed @code{mysqld} or the machine in the middle
+of an update.
+@item
+You have found a bug in @code{mysqld} that caused it to die in the
+middle of an update.
+@item
+Someone is manipulating the data/index files outside of @strong{mysqld}
+without locking the table properly.
+@item
+If you are running many @code{mysqld} servers on the same data on a
+system that doesn't support good file system locks (normally handled by
+the @code{lockd} deamon.) or if you are running
+multiple servers with @code{--skip-locking}
+@item
+You have a crashed index/data file that contains very wrong data that
+got mysqld confused.
+@item
+You have found a bug in the data storage code. This isn't that likely,
+but it's at least possible. In this case you can try to change the file
+type to another database handler by using @code{ALTER TABLE} on a
+repaired copy of the table!
+@end itemize
+
+Because it is very difficult to know why something is crashing, first try to
+check whether or not things that work for others crash for you. Please try
+the following things:
+
+@itemize @bullet
+@item
+Take down the @code{mysqld} daemon with @code{mysqladmin shutdown}, run
+@code{myisamchk --silent --force */*.MYI} on all tables and restart the
+@code{mysqld} daemon. This will ensure that you are running from a clean
+state. @xref{Maintenance}.
+
+@item
+Use @code{mysqld --log} and try to determine from the information in the log
+whether or not some specific query kills the server. 95% of all bugs are
+related to a particular query! Normally this is one of the last queries in
+the log file just before @strong{MySQL} restarted.
+
+You may be able to verify this using the following procedure:
+
+@itemize @bullet
+@item
+Take down the @strong{MySQL} daemon (with @code{mysqladmin shutdown})
+@item
+Make a backup of files in the @strong{MySQL} database directory.
+(As the server is stopped, you can just copy the files to some other
+directory)
+@item
+Check the tables with @code{myisamchk -s */*.MYI} to verify that all
+tables are correct. If any table is corrupted, repair it with
+@code{myisamchk -r path-to-table.MYI}. You should take the backup
+before checking the tables as the problem could be related to corrupted
+tables.
+@item
+Remove (or move away) any old log files from the @strong{MySQL} data directory.
+@item
+Start the server with @code{safe_mysqld --log-update} or
+@code{safe_mysqld --log --log-update}.
+@item
+If @code{mysqld} now dies, you have two options:
+@itemize @bullet
+@item
+First take a backup of your backup database. (Just copy the file(s)
+somewhere again). This is because we want to keep the original start
+situation untouched. Start a mysqld process on the other backup database
+(you can do this with option @code{--datadir=/path/to/backup/}).
+@item
+Just restore the backup on your original database and restart @code{mysqld}.
+You will not any lose information, because you have the @code{log-update} file.
+@end itemize
+@item
+
+Now you can test if the problem is a specific update statement by executing
+@code{mysql database_name < path-to-log-update-file}.
+
+You can also use the script @code{mysql_find_rows} to just execute some of the
+update statements if you want to narrow down the problem.
+
+If mysqld now crashes, then you have something repeatable
+available. Please mail @email{bugs@@lists.mysql.com}, or
+@email{developers@@mysql.com}, or (if you are a support customer) to
+@email{support@@mysql.com} about the problem and the @strong{MySQL} team
+will fix it as soon as possible.
+@end itemize
+
+@item
+Have you tried the benchmarks? They should test @strong{MySQL} rather well.
+You can also add code that simulates your application! The benchmarks can be
+found in the @file{bench} directory in the source distribution, or, for a
+binary distribution, in the @file{sql-bench} directory under your
+@strong{MySQL} installation directory.
+
+@item
+Try @code{fork_test.pl} and @code{fork2_test.pl}.
+
+@item
+Check the file @file{mysql-data-directory/'hostname'.err} for any errors.
+
+@item
+If you configure @strong{MySQL} for debugging, it will be much easier to
+gather information about possible errors if something goes wrong.
+Reconfigure @strong{MySQL} with the @code{--with-debug} option to
+@code{configure} and then recompile. @xref{Debugging server}.
+
+@item
+Configuring @strong{MySQL} for debugging causes a safe memory allocator to be
+included that can find some errors. It also provides a lot of output about
+what is happening.
+
+@item
+Have you applied the latest patches for your operating system?
+
+@item
+Use the @code{--skip-locking} option to @code{mysqld}. On some systems, the
+@code{lockd} lock manager does not work properly; the @code{--skip-locking}
+option tells @code{mysqld} not to use external locking. (This means that you
+cannot run 2 @code{mysqld} servers on the same data and that you must be
+careful if you use @code{myisamchk}, but it may be instructive to try the
+option as a test.)
+
+@item
+Have you tried @code{mysqladmin -u root processlist} when @code{mysqld}
+appears to be running but not responding? Sometimes @code{mysqld} is not
+comatose even though you might think so. The problem may be that all
+connections are in use, or there may be some internal lock problem.
+@code{mysqladmin processlist} will usually be able to make a connection even
+in these cases, and can provide useful information about the current number
+of connections and their status.
+
+@item
+Run the command @code{mysqladmin -i 5 status}
+in a separate window to produce statistics while you run your other queries.
+
+@item
+Try the following:
+@enumerate
+@item
+Start @code{mysqld} from @code{gdb} (or in another debugger).
+
+@item
+Run your test scripts.
+
+@item
+Print the backtrace and the local variables at the 3 lowest levels. In gdb you
+can do this with the following commands when @code{mysqld} has crashed inside
+gdb:
+
+@example
+backtrace
+info local
+up
+info local
+up
+info local
+@end example
+
+With gdb you can also examine which threads there exists with @code{info
+threads} and switch to a specific thread with @code{thread #}, where
+@code{#} is the thread id.
+@end enumerate
+
+@item
+Try to simulate your application with a Perl script to force
+@strong{MySQL} to crash or misbehave.
+
+@item
+Send a normal bug report. @xref{Bug reports}. Be even more detailed
+than usual. Because @strong{MySQL} works for many people, it may be that the
+crash results from something that exists only on your computer (for example,
+an error that is related to your particular system libraries).
+@item
+If you have a problem with table with dynamic length rows and you are
+not using @code{BLOB/TEXT} columns (but only @code{VARCHAR} columns) you
+can try to change all @code{VARCHAR} to @code{CHAR} with @code{ALTER
+TABLE}. This will force @strong{MySQL} to use fixed size rows. Fixed
+size rows take a little extra space, but are much more tolerant to
+corruption!
+
+The current dynamic row code has been in use at MySQL AB for at least 3
+years without any problems, but by nature dynamic length rows are more
+prone to errors, so it may be a good idea to try the above to see if it helps!
+@end itemize
+
+@node Link errors, Common errors, Crashing, Problems
+@section Problems when linking with the MySQL client library
+
+If you are linking your program and you get errors for unreferenced
+symbols that starts with @code{mysql_}, like the following:
+
+@example
+/tmp/ccFKsdPa.o: In function `main':
+/tmp/ccFKsdPa.o(.text+0xb): undefined reference to `mysql_init'
+/tmp/ccFKsdPa.o(.text+0x31): undefined reference to `mysql_real_connect'
+/tmp/ccFKsdPa.o(.text+0x57): undefined reference to `mysql_real_connect'
+/tmp/ccFKsdPa.o(.text+0x69): undefined reference to `mysql_error'
+/tmp/ccFKsdPa.o(.text+0x9a): undefined reference to `mysql_close'
+@end example
+
+you should be able to solve this by adding @code{-Lpath-to-the-mysql-library
+-lmysqlclient} @strong{LAST} on your link line.
+
+If you get @code{undefined reference} errors for the @code{compress} function,
+add @code{-lgz} @strong{LAST} on your link line and try again!
+
+If you get @code{undefined reference} errors for functions that should
+exist on your system, like @code{connect}, check the man page, for the
+function in question, for which libraries you should add to the link
+line!
+
+If you get @code{undefined reference} errors for functions that doesn't
+exist on your system, like the following:
+
+@example
+mf_format.o(.text+0x201): undefined reference to `__lxstat'
+@end example
+
+It usually means that your library is compiled on a system that is not
+100 % compatible with yours. In this case you should download the
+latest @strong{MySQL} source distribution and compile this yourself.
+@xref{Installing source}.
+
+If you are trying to run a program and you then get errors for
+unreferenced symbols that starts with @code{mysql_} or that the
+@code{mysqlclient} library can't be found, this means that your system
+can't find the share @code{libmysqlclient.so} library.
+
+The fix for this is to either tell your system to search after shared
+libraries where the library is located by one of the following methods:
+
+@itemize @bullet
+@item
+Add the path to directory where you have @code{libmysqlclient.so} the
+@code{LD_LIBRARY_PATH} environment variable.
+@item
+Add the path to directory where you have @code{libmysqlclient.so} the
+@code{LD_LIBRARY} environment variable.
+@item
+Copy @code{libmysqlclient.so} to some place that is searched by your system,
+like @file{/lib} and update the shared library information by executing
+@code{ldconfig}.
+@end itemize
+
+Another way to solve this problem is to link your program staticly, with
+@code{-static}, or by removing the dynamic @strong{MySQL} libraries
+before linking your code. In the second case you should of course be
+sure that no other programs is using the dynamic libraries!
+
+@node Common errors, Full disk, Link errors, Problems
+@section Some common errors when using MySQL
+
+@menu
+* Gone away:: @code{MySQL server has gone away} error
+* Can not connect to server:: @code{Can't connect to [local] MySQL server} error
+* Blocked host:: @code{Host '...' is blocked} error
+* Too many connections:: @code{Too many connections} error
+* Out of memory:: @code{Out of memory} error
+* Packet too large:: @code{Packet too large} error
+* Communication errors::
+* Full table:: @code{The table is full} error
+* Commands out of sync:: @code{Commands out of sync} error in client
+* Ignoring user:: @code{Ignoring user} error
+* Cannot find table:: @code{Table 'xxx' doesn't exist} error
+@end menu
+
+@node Gone away, Can not connect to server, Common errors, Common errors
+@subsection @code{MySQL server has gone away} error
+
+This section also covers the related @code{Lost connection to server
+during query} error.
+
+The most common reason for the @code{MySQL server has gone away} error
+is that the server timed out and closed the connection. By default, the
+server closes the connection after 8 hours if nothing has happened. You
+can change the time limit with by setting the @code{wait_timeout} variable when
+you start mysqld.
+
+You can check that the @strong{MySQL} hasn't died by executing
+@code{mysqladmin version} and examining the uptime.
+
+If you have a script, you just have to issue the query again for the client
+to do an automatic reconnection.
+
+You normally can get the following error codes in this case
+(which one you get is OS-dependent):
+
+@multitable @columnfractions .3 .7
+@item @code{CR_SERVER_GONE_ERROR} @tab The client couldn't send a question to the
+server.
+@item @code{CR_SERVER_LOST} @tab The client didn't get an error when writing
+to the server, but it didn't get a full answer (or any answer) to the question.
+@end multitable
+
+You can also get these errors if you send a query to the server that is
+incorrect or too large. If @code{mysqld} gets a packet that is too large
+or out of order, it assumes that something has gone wrong with the client and
+closes the connection. If you need big queries (for example, if you are
+working with big @code{BLOB} columns), you can increase the query limit by
+starting @code{mysqld} with the @code{-O max_allowed_packet=#} option
+(default 1M). The extra memory is allocated on demand, so @code{mysqld} will
+use more memory only when you issue a big query or when @code{mysqld} must
+return a big result row!
+
+@node Can not connect to server, Blocked host, Gone away, Common errors
+@subsection @code{Can't connect to [local] MySQL server} error
+
+A @strong{MySQL} client on Unix can connect to the @code{mysqld} server in two
+different ways: Unix sockets, which connect through a file in the file
+system (default @file{/tmp/mysqld.sock}), or TCP/IP, which connects
+through a port number. Unix sockets are faster than TCP/IP but can only
+be used when connecting to a server on the same computer. Unix sockets
+are used if you don't specify a hostname or if you specify the special
+hostname @code{localhost}.
+
+On Windows you can connect only with TCP/IP if the @code{mysqld} server
+is running on Win95/Win98. If it's running on NT, you can also connect
+with named pipes. The name of the named pipe is @code{MySQL}. If you
+don't give a hostname when connecting to @code{mysqld}, a @strong{MySQL} client
+will first try to connect to the named pipe and if this doesn't work it
+will connect to the TCP/IP port. You can force the use of named pipes
+on Windows by using @code{.} as the hostname.
+
+The error (2002) @code{Can't connect to ...} normally means that there
+isn't a @strong{MySQL} server running on the system or that you are
+using a wrong socket file or TCP/IP port when trying to connect to the
+@code{mysqld} server.
+
+Start by checking (using @code{ps} or the task manager on Windows) that
+there is a process running named @code{mysqld} on your server! If there
+isn't any @code{mysqld} process, you should start one. @xref{Starting
+server}.
+
+If a @code{mysqld} process is running, you can check the server by
+trying these different connections (the port number and socket pathname
+might be different in your setup, of course):
+
+@example
+shell> mysqladmin version
+shell> mysqladmin variables
+shell> mysqladmin -h `hostname` version variables
+shell> mysqladmin -h `hostname` --port=3306 version
+shell> mysqladmin -h 'ip for your host' version
+shell> mysqladmin --socket=/tmp/mysql.sock version
+@end example
+
+Note the use of backquotes rather than forward quotes with the @code{hostname}
+command; these cause the output of @code{hostname} (i.e., the current
+hostname) to be substituted into the @code{mysqladmin} command.
+
+Here are some reasons the @code{Can't connect to local MySQL server}
+error might occur:
+
+@itemize @bullet
+@item @code{mysqld} is not running.
+@item You are running on a system that uses MIT-pthreads.
+If you are running on a system that doesn't have native threads, @code{mysqld}
+uses the MIT-pthreads package.
+@xref{Which OS}.
+However, MIT-pthreads doesn't support Unix sockets, so on such a system you
+must always specify the hostname explicitly when connecting to the server.
+Try using this command to check the connection to the server:
+@example
+shell> mysqladmin -h `hostname` version
+@end example
+@item Someone has removed the Unix socket that @code{mysqld} uses (default
+@file{/tmp/mysqld.sock}). You might have a @code{cron} job that removes the
+@strong{MySQL} socket (e.g., a job that removes old files from the @file{/tmp}
+directory). You can always run @code{mysqladmin version} and
+check that the socket @code{mysqladmin} is trying to use really exists.
+The fix in this case is to change the @code{cron} job to not remove
+@file{mysqld.sock} or to place the socket somewhere else. You can specify
+a different socket location at @strong{MySQL} configuration time with this
+command:
+@example
+shell> ./configure --with-unix-socket-path=/path/to/socket
+@end example
+You can also start @code{safe_mysqld} with the
+@code{--socket=/path/to/socket} option and set the environment variable
+@code{MYSQL_UNIX_PORT} to the socket pathname before starting your
+@strong{MySQL} clients. @item You have started the @code{mysqld} server with
+the @code{--socket=/path/to/socket} option. If you change the socket
+pathname for the server, you must also notify the @strong{MySQL} clients
+about the new path. You can do this by setting the environment variable
+@code{MYSQL_UNIX_PORT} to the socket pathname or by providing the socket path
+as an argument to the clients. You can test the socket with this command:
+
+@example
+shell> mysqladmin --socket=/path/to/socket version
+@end example
+@item
+You are using Linux and one thread has died (core dumped). In this case
+you must kill the other @code{mysqld} threads (for example with the
+@code{mysql_zap} script before you can start a new @strong{MySQL}
+server. @xref{Crashing}.
+@end itemize
+
+If you get the error message @code{Can't connect to MySQL server on
+some_hostname}, you can try the following things to find out what is the
+problem:
+
+@itemize @bullet
+@item
+Check if the server up by doing @code{telnet your-host-name
+tcp-ip-port-number} and press @code{RETURN} a couple of times. If there
+is a @strong{MySQL} server running on this port you should get a
+responses that includes the version number of the running @strong{MySQL}
+server. If you get an error like @code{telnet: Unable to connect to
+remote host: Connection refused}, then there is no server running on the
+given port.
+@item
+Try connecting to the @code{mysqld} daemon on the local machine and check
+the TCP/IP port that mysqld it's configured to use (variable @code{port}) with
+@code{mysqladmin variables}.
+@item
+Check that your @code{mysqld} server is not started with the
+@code{--skip-networking} option.
+@end itemize
+
+@node Blocked host, Too many connections, Can not connect to server, Common errors
+@subsection @code{Host '...' is blocked} error
+
+If you get an error like this:
+
+@example
+Host 'hostname' is blocked because of many connection errors.
+Unblock with 'mysqladmin flush-hosts'
+@end example
+
+This means that @code{mysqld} has gotten a lot (@code{max_connect_errors})
+of connect requests from the host @code{'hostname'} that have been interrupted
+in the middle. After @code{max_connect_errors} failed requests, @code{mysqld}
+assumes that something is wrong (like an attack from a cracker), and
+blocks the site from further connections until someone executes the command
+@code{mysqladmin flush-hosts}.
+
+By default, @code{mysqld} blocks a host after 10 connection errors.
+You can easily adjust this by starting the server like this:
+
+@example
+shell> safe_mysqld -O max_connect_errors=10000 &
+@end example
+
+Note that if you get this error message for a given host, you should first
+check that there isn't anything wrong with TCP/IP connections from that
+host. If your TCP/IP connections aren't working, it won't do you any good to
+increase the value of the @code{max_connect_errors} variable!
+
+@node Too many connections, Out of memory, Blocked host, Common errors
+@subsection @code{Too many connections} error
+
+If you get the error @code{Too many connections} when you try to connect
+to @strong{MySQL}, this means that there is already @code{max_connections}
+clients connected to the @code{mysqld} server.
+
+If you need more connections than the default (100), then you should restart
+@code{mysqld} with a bigger value for the @code{max_connections} variable.
+
+Note that @code{mysqld} actually allows (@code{max_connections}+1) clients to connect.
+The last connection is reserved for a user with the @strong{process} privilege.
+By not giving this privilege to normal users (they shouldn't need this), an
+administrator with this privilege can login and use @code{SHOW PROCESSLIST}
+to find out what could be wrong. @xref{SHOW}.
+
+@node Out of memory, Packet too large, Too many connections, Common errors
+@subsection @code{Out of memory} error
+
+If you issue a query and get something like the following error:
+
+@example
+mysql: Out of memory at line 42, 'malloc.c'
+mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k)
+ERROR 2008: MySQL client ran out of memory
+@end example
+
+Note that the error refers to the @strong{MySQL} client @code{mysql}. The
+reason for this error is simply that the client does not have enough memory to
+store the whole result.
+
+To remedy the problem, first check that your query is correct. Is it
+reasonable that it should return so many rows? If so,
+you can use @code{mysql --quick}, which uses @code{mysql_use_result()}
+to retrieve the result set. This places less of a load on the client (but
+more on the server).
+
+@node Packet too large, Communication errors, Out of memory, Common errors
+@subsection @code{Packet too large} error
+
+When a @strong{MySQL} client or the @code{mysqld} server gets a packet bigger
+than @code{max_allowed_packet} bytes, it issues a @code{Packet too large}
+error and closes the connection.
+
+If you are using the @code{mysql} client, you may specify a bigger buffer by
+starting the client with @code{mysql --set-variable=max_allowed_packet=8M}.
+
+If you are using other clients that do not allow you to specify the maximum
+packet size (such as @code{DBI}), you need to set the packet size when you
+start the server. You cau use a command-line option to @code{mysqld} to set
+@code{max_allowed_packet} to a larger size. For example, if you are
+expecting to store the full length of a @code{BLOB} into a table, you'll need
+to start the server with the @code{--set-variable=max_allowed_packet=24M}
+option.
+
+@cindex Aborted connection
+@node Communication errors, Full table, Packet too large, Common errors
+@subsection Communication errors / Aborted connection
+
+If you find the error @code{Aborted connection} in the @code{hostname.err}
+log file this could be because on of the following reasons:
+
+@itemize @bullet
+@item
+The client had been sleeping more than @code{wait_timeout} without doing
+any requests. @xref{SHOW VARIABLES}.
+@item
+The client program ended abruptly in the middle of the transfer
+@item
+The client program did not call @code{mysql_close()} before exit
+@item
+Usage of duplex Ethernet protocol, both half and full with
+Linux. Many Linux Ethernet drivers have this bug. You should test
+for this bug by transferring a huge file via ftp between these tow
+machines. If a transfer goes in burst-pause-burst-pause .. mode then
+you are experiencing a Linux duplex syndrome. The only solution to
+this problem is switching of both half and full duplexing on hubs
+and switches
+@item
+Some problem with the thread library that causes interrupts on reads.
+@item
+Badly configured TCP/IP
+@item
+Faulty Ethernets or hubs or switches, cables .. This can be diagnosed
+properly only by replacing hardware
+@end itemize
+
+@cindex The table is full
+@node Full table, Commands out of sync, Communication errors, Common errors
+@subsection @code{The table is full} error
+
+This error occurs in older @strong{MySQL} versions when an in-memory temporary
+table becomes larger than @code{tmp_table_size} bytes. To avoid this
+problem, you can use the @code{-O tmp_table_size=#} option to
+@code{mysqld} to increase the temporary table size, or use the SQL
+option @code{SQL_BIG_TABLES} before you issue the problematic
+query. @xref{SET OPTION, , @code{SET OPTION}}.
+
+You can also start @code{mysqld} with the @code{--big-tables} option.
+This is exactly the same as using @code{SQL_BIG_TABLES} for all queries.
+
+In @strong{MySQL} 3.23 in-memory temporary tables will automaticly be
+converted to a disk based @code{MyISAM} table after the table size gets
+bigger than @code{tmp_table_size}.
+
+@cindex Commands out of sync
+@node Commands out of sync, Ignoring user, Full table, Common errors
+@subsection @code{Commands out of sync} error in client
+
+If you get @code{Commands out of sync; You can't run this command now}
+in your client code, you are calling client functions in the wrong order!
+
+This can happen, for example, if you are using @code{mysql_use_result()} and
+try to execute a new query before you have called @code{mysql_free_result()}.
+It can also happen if you try to execute two queries that return data without
+a @code{mysql_use_result()} or @code{mysql_store_result()} in between.
+
+@node Ignoring user, Cannot find table, Commands out of sync, Common errors
+@subsection @code{Ignoring user} error
+
+If you get the following error:
+
+@code{Found wrong password for user: 'some_user@@some_host'; Ignoring user}
+
+This means that when @code{mysqld} was started or when it reloaded the
+permissions tables, it found an entry in the @code{user} table with
+an invalid password. As a result, the entry is simply ignored by the
+permission system.
+
+Possible causes of and fixes for this problem:
+
+@itemize @bullet
+@item
+You may be running a new version of @code{mysqld} with an old
+@code{user} table.
+You can check this by executing @code{mysqlshow mysql user} to see if
+the password field is shorter than 16 characters. If so, you can correct this
+condition by running the @code{scripts/add_long_password} script.
+
+@item
+The user has an old password (8 chararacters long) and you didn't start
+@code{mysqld} with the @code{--old-protocol} option.
+Update the user in the @code{user} table with a new password or
+restart @code{mysqld} with @code{--old-protocol}.
+
+@item
+@findex PASSWORD()
+You have specified a password in the @code{user} table without using the
+@code{PASSWORD()} function. Use @code{mysql} to update the user in the
+@code{user} table with a new password. Make sure to use the @code{PASSWORD()}
+function:
+
+@example
+mysql> update user set password=PASSWORD('your password')
+ where user='XXX';
+@end example
+@end itemize
+
+@node Cannot find table, , Ignoring user, Common errors
+@subsection @code{Table 'xxx' doesn't exist} error
+
+If you get the error @code{Table 'xxx' doesn't exist} or @code{Can't
+find file: 'xxx' (errno: 2)}, this means that no table exists
+in the current database with the name @code{xxx}.
+
+Note that as @strong{MySQL} uses directories and files to store databases and
+tables, the database and table names are @strong{case sensitive}!
+(On Win32 the databases and tables names are not case sensitive, but all
+references to a given table within a query must use the same case!)
+
+You can check which tables you have in the current database with
+@code{SHOW TABLES}. @xref{SHOW, , @code{SHOW}}.
+
+@cindex Full disk
+@cindex Disk full
+@node Full disk, Multiple sql commands, Common errors, Problems
+@section How MySQL handles a full disk
+
+@noindent
+When a disk full condition occurs, @strong{MySQL} does the following:
+
+@itemize @bullet
+@item
+It checks once every minute to see whether or not there is enough space to
+write the current row. If there is enough space, it continues as if nothing had
+happened.
+@item
+Every 6 minutes it writes an entry to the log file warning about the disk
+full condition.
+@end itemize
+
+@noindent
+To alleviate the problem, you can take the following actions:
+
+@itemize @bullet
+@item
+To continue, you only have to free enough disk space to insert all records.
+@item
+To abort the thread, you must send a @code{mysqladmin kill} to the thread.
+The thread will be aborted the next time it checks the disk (in 1 minute).
+@item
+Note that other threads may be waiting for the table that caused the ``disk
+full'' condition. If you have several ``locked'' threads, killing the one
+thread that is waiting on the disk full condition will allow the other
+threads to continue.
+@end itemize
+
+@node Multiple sql commands, Temporary files, Full disk, Problems
+@section How to run SQL commands from a text file
+
+The @code{mysql} client typically is used interactively, like this:
+
+@example
+shell> mysql database
+@end example
+
+However, it's also possible to put your SQL commands in a file and tell
+@code{mysql} to read its input from that file. To do so, create a text
+file @file{text_file} that contains the commands you wish to execute.
+Then invoke @code{mysql} as shown below:
+
+@example
+shell> mysql database < text_file
+@end example
+
+You can also start your text file with a @code{USE db_name} statement. In
+this case, it is unnecessary to specify the database name on the command
+line:
+
+@example
+shell> mysql < text_file
+@end example
+
+@xref{Programs}.
+
+@node Temporary files, Problems with mysql.sock, Multiple sql commands, Problems
+@section Where MySQL stores temporary files
+
+@strong{MySQL} uses the value of the @code{TMPDIR} environment variable as
+the pathname of the directory in which to store temporary files. If you don't
+have @code{TMPDIR} set, @strong{MySQL} uses the system default, which is
+normally @file{/tmp} or @file{/usr/tmp}. If the file system containing your
+temporary file directory is too small, you should edit @code{safe_mysqld} to
+set @code{TMPDIR} to point to a directory in a file system where you have
+enough space! You can also set the temporary directory using the
+@code{--tmpdir} option to @code{mysqld}.
+
+@strong{MySQL} creates all temporary files as ``hidden files''. This ensures
+that the temporary files will be removed if @code{mysqld} is terminated. The
+disadvantage of using hidden files is that you will not see a big temporary
+file that fills up the file system in which the temporary file directory is
+located.
+
+When sorting (@code{ORDER BY} or @code{GROUP BY}), @strong{MySQL} normally
+uses one or two temporary files. The maximum disk-space needed is:
+
+@example
+(length of what is sorted + sizeof(database pointer))
+* number of matched rows
+* 2
+@end example
+
+@code{sizeof(database pointer)} is usually 4, but may grow in the future for
+really big tables.
+
+For some @code{SELECT} queries, @strong{MySQL} also creates temporary SQL
+tables. These are not hidden and have names of the form @file{SQL_*}.
+
+@code{ALTER TABLE} and @code{OPTIMIZE TABLE} create a temporary table in the
+same directory as the original table.
+
+@node Problems with mysql.sock, Error Access denied, Temporary files, Problems
+@section How to protect @file{/tmp/mysql.sock} from being deleted
+
+If you have problems with the fact that anyone can delete the
+@strong{MySQL} communication socket @file{/tmp/mysql.sock}, you can,
+on most versions of Unix, protect your @file{/tmp} file system by setting
+the @code{sticky} bit on it. Log in as @code{root} and do the following:
+
+@example
+shell> chmod +t /tmp
+@end example
+
+This will protect your @file{/tmp} file system so that files can be deleted
+only by their owners or the superuser (@code{root}).
+
+You can check if the @code{sticky} bit is set by executing @code{ls -ld /tmp}.
+If the last permission bit is @code{t}, the bit is set.
+
+@node Error Access denied, Changing MySQL user , Problems with mysql.sock, Problems
+@section @code{Access denied} error
+
+@xref{Privileges}. And especially see @ref{Access denied}.
+
+@node Changing MySQL user , Resetting permissions, Error Access denied, Problems
+@section How to run MySQL as a normal user
+
+The @strong{MySQL} server @code{mysqld} can be started and run by any user.
+In order to change @code{mysqld} to run as Unix user @code{user_name}, you must
+do the following:
+
+@enumerate
+@item
+Stop the server if it's running (use @code{mysqladmin shutdown}).
+
+@item
+Change the database directories and files so that @code{user_name} has
+privileges to read and write files in them (you may need to do this as
+the Unix @code{root} user):
+
+@example
+shell> chown -R user_name /path/to/mysql/datadir
+@end example
+
+If directories or files within the @strong{MySQL} data directory are
+symlinks, you'll also need to follow those links and change the directories
+and files they point to. @code{chown -R} may not follow symlinks for
+you.
+
+@item
+Start the server as user @code{user_name}, or, if you are using
+@strong{MySQL} 3.22 or later, start @code{mysqld} as the Unix @code{root}
+user and use the @code{--user=user_name} option. @code{mysqld} will switch
+to run as Unix user @code{user_name} before accepting any connections.
+
+@item
+If you are using the @code{mysql.server} script to start @code{mysqld} when
+the system is rebooted, you should edit @code{mysql.server} to use @code{su}
+to run @code{mysqld} as user @code{user_name}, or to invoke @code{mysqld}
+with the @code{--user} option. (No changes to @code{safe_mysqld} are
+necessary.)
+@end enumerate
+
+At this point, your @code{mysqld} process should be running fine and dandy as
+the Unix user @code{user_name}. One thing hasn't changed, though: the
+contents of the permissions tables. By default (right after running the
+permissions table install script @code{mysql_install_db}), the @strong{MySQL}
+user @code{root} is the only user with permission to access the @code{mysql}
+database or to create or drop databases. Unless you have changed those
+permissions, they still hold. This shouldn't stop you from accessing
+@strong{MySQL} as the @strong{MySQL} @code{root} user when you're logged in
+as a Unix user other than @code{root}; just specify the @code{-u root} option
+to the client program.
+
+Note that accessing @strong{MySQL} as @code{root}, by supplying @code{-u
+root} on the command line, has @emph{nothing} to do with @strong{MySQL} running
+as the Unix @code{root} user, or, indeed, as other Unix user. The access
+permissions and user names of @strong{MySQL} are completely separate from
+Unix user names. The only connection with Unix user names is that if you
+don't provide a @code{-u} option when you invoke a client program, the client
+will try to connect using your Unix login name as your @strong{MySQL} user
+name.
+
+If your Unix box itself isn't secured, you should probably at least put a
+password on the @strong{MySQL} @code{root} users in the access tables.
+Otherwise, any user with an account on that machine can run @code{mysql -u
+root db_name} and do whatever he likes.
+
+@node Resetting permissions, File permissions , Changing MySQL user , Problems
+@section How to reset a forgotten password.
+
+If you have forgotten the @code{root} user password for @strong{MySQL}, you
+can restore it with the following procedure.
+
+@enumerate
+@item
+Take down the mysqld server by sending a @code{kill} (not @code{kill
+-9}) to the @code{mysqld} server. The pid is stored in a @code{.pid}
+file which is normally in the @strong{MySQL} database directory:
+
+@example
+kill `cat /mysql-data-directory/hostname.pid`
+@end example
+
+You must be either the Unix @code{root} user or the same user the server
+runs as to do this.
+
+@item
+Restart @code{mysqld} with the @code{--skip-grant-tables} option.
+@item
+Connect to the mysqld server with @code{mysql -h hostname mysql} and change
+the password with a @code{GRANT} command. @xref{GRANT,,@code{GRANT}}.
+You can also do this with
+@code{mysqladmin -h hostname -u user password 'new password'}
+@item
+Load the privilege tables with: @code{mysqladmin -h hostname
+flush-privileges} or with the SQL command @code{FLUSH PRIVILEGES}.
+@end enumerate
+
+@node File permissions , Not enough file handles, Resetting permissions, Problems
+@section Problems with file permissions
+
+If you have problems with file permissions, for example, if @code{mysql}
+issues the following error message when you create a table:
+
+@example
+ERROR: Can't find file: 'path/with/filename.frm' (Errcode: 13)
+@end example
+
+@tindex UMASK environment variable
+@tindex Environment variable, UMASK
+Then the environment variable @code{UMASK} might be set incorrectly when
+@code{mysqld} starts up. The default umask value is @code{0660}. You can
+change this behavior by starting @code{safe_mysqld} as follows:
+
+@example
+shell> UMASK=384 # = 600 in octal
+shell> export UMASK
+shell> /path/to/safe_mysqld &
+@end example
+
+@tindex UMASK_DIR environment variable
+@tindex Environment variable, UMASK_DIR
+By default @strong{MySQL} will create database and @code{RAID}
+directories with permission type 0700. You can modify this behaviour by
+setting the the @code{UMASK_DIR} variable. If you set this, new
+directories are created with the combined @code{UMASK} and
+@code{UMASK_DIR}. For example, if you want to give group access to
+all new directories, you can do:
+
+@example
+shell> UMASK_DIR=504 # = 770 in octal
+shell> export UMASK_DIR
+shell> /path/to/safe_mysqld &
+@end example
+
+@xref{Environment variables}.
+
+@node Not enough file handles, Using DATE, File permissions , Problems
+@section File not found
+
+If you get @code{ERROR '...' not found (errno: 23)}, @code{Can't open
+file: ... (errno: 24)} or any other error with @code{errno 23} or
+@code{errno 24} from @strong{MySQL}, it means that you haven't allocated
+enough file descriptors for @strong{MySQL}. You can use the
+@code{perror} utility to get a description of what the error number
+means:
+
+@example
+shell> perror 23
+File table overflow
+shell> perror 24
+Too many open files
+@end example
+
+The problem here is that @code{mysqld} is trying to keep open too many
+files simultaneously. You can either tell @code{mysqld} not to open so
+many files at once, or increase the number of file descriptors
+available to @code{mysqld}.
+
+To tell @code{mysqld} to keep open fewer files at a time, you can make the
+table cache smaller by using the @code{-O table_cache=32} option
+to @code{safe_mysqld} (the default value is 64). Reducing the value of
+@code{max_connections} will also reduce the number of open files (the default
+value is 90).
+
+@tindex ulimit
+To change the number of file descriptors available to @code{mysqld}, modify
+the @code{safe_mysqld} script. There is a commented-out line
+@code{ulimit -n 256} in the script. You can remove the @code{'#'} character
+to uncomment this line, and change the number 256 to change the number of
+file descriptors available to @code{mysqld}.
+
+@code{ulimit} can increase the number of file descriptors, but only up to the
+limit imposed by the operating system. If you need to increase the OS limit
+on the number of file descriptors available to each process, consult the
+documentation for your operating system.
+
+Note that if you run the @code{tcsh} shell, @code{ulimit} will not work!
+@code{tcsh} will also report incorrect values when you ask for the current
+limits! In this case you should start @code{safe_mysqld} with @code{sh}!
+
+@node Using DATE, Timezone problems, Not enough file handles, Problems
+@section Problems using @code{DATE} columns
+
+The format of a @code{DATE} value is @code{'YYYY-MM-DD'}. According to ANSI
+SQL, no other format is allowed. You should use this format in @code{UPDATE}
+expressions and in the WHERE clause of @code{SELECT} statements. For
+example:
+
+@example
+mysql> SELECT * FROM tbl_name WHERE date >= '1997-05-05';
+@end example
+
+As a convenience, @strong{MySQL} automatically converts a date to a number if
+the date is used in a numeric context (and vice versa). It is also smart
+enough to allow a ``relaxed'' string form when updating and in a @code{WHERE}
+clause that compares a date to a @code{TIMESTAMP}, @code{DATE} or a
+@code{DATETIME} column. (Relaxed form means that any punctuation character
+may be used as the separator between parts. For example, @code{'1998-08-15'}
+and @code{'1998#08#15'} are equivalent.) @strong{MySQL} can also convert a
+string containing no separators (such as @code{'19980815'}), provided it
+makes sense as a date.
+
+The special date @code{'0000-00-00'} can be stored and retrieved as
+@code{'0000-00-00'.} When using a @code{'0000-00-00'} date through
+@strong{MyODBC}, it will automatically be converted to @code{NULL} in
+@strong{MyODBC} 2.50.12 and above, because ODBC can't handle this kind of
+date.
+
+Because @strong{MySQL} performs the conversions described above, the following
+statements work:
+
+@example
+mysql> INSERT INTO tbl_name (idate) VALUES (19970505);
+mysql> INSERT INTO tbl_name (idate) VALUES ('19970505');
+mysql> INSERT INTO tbl_name (idate) VALUES ('97-05-05');
+mysql> INSERT INTO tbl_name (idate) VALUES ('1997.05.05');
+mysql> INSERT INTO tbl_name (idate) VALUES ('1997 05 05');
+mysql> INSERT INTO tbl_name (idate) VALUES ('0000-00-00');
+
+mysql> SELECT idate FROM tbl_name WHERE idate >= '1997-05-05';
+mysql> SELECT idate FROM tbl_name WHERE idate >= 19970505;
+mysql> SELECT mod(idate,100) FROM tbl_name WHERE idate >= 19970505;
+mysql> SELECT idate FROM tbl_name WHERE idate >= '19970505';
+@end example
+
+@noindent
+However, the following will not work:
+
+@example
+mysql> SELECT idate FROM tbl_name WHERE STRCMP(idate,'19970505')=0;
+@end example
+
+@code{STRCMP()} is a string function, so it converts @code{idate} to
+a string and performs a string comparison. It does not convert
+@code{'19970505'} to a date and perform a date comparison.
+
+Note that @strong{MySQL} does no checking whether or not the date is
+correct. If you store an incorrect date, such as @code{'1998-2-31'}, the
+wrong date will be stored. If the date cannot be converted to any reasonable
+value, a @code{0} is stored in the @code{DATE} field. This is mainly a speed
+issue and we think it is up to the application to check the dates, and not
+the server.
+
+@cindex Timezone problems
+@tindex TZ environment variable
+@tindex Environment variable, TZ
+@node Timezone problems, Case sensitivity, Using DATE, Problems
+@section Timezone problems
+
+If you have a problem with @code{SELECT NOW()} returning values in GMT and
+not your local time, you have to set the @code{TZ} environment variable to
+your current timezone. This should be done for the environment in which
+the server runs, for example in @code{safe_mysqld} or @code{mysql.server}.
+@xref{Environment variables}.
+
+@cindex Case sensitivity, in searches
+@cindex Chinese
+@cindex Big5 Chinese character encoding
+@node Case sensitivity, Problems with NULL, Timezone problems, Problems
+@section Case sensitivity in searches
+
+By default, @strong{MySQL} searches are case-insensitive (although there are
+some character sets that are never case insensitive, such as @code{czech}).
+That means that if you search with @code{col_name LIKE 'a%'}, you will get all
+column values that start with @code{A} or @code{a}. If you want to make this
+search case-sensitive, use something like @code{INDEX(col_name, "A")=0} to
+check a prefix. Or use @code{STRCMP(col_name, "A") = 0} if the column value
+must be exactly @code{"A"}.
+
+Simple comparison operations (@code{>=, >, = , < , <=}, sorting and
+grouping) are based on each character's ``sort value''. Characters with
+the same sort value (like E, e and é) are treated as the same character!
+
+In older @strong{MySQL} versions @code{LIKE} comparisons where done on
+the uppercase value of each character (E == e but E <> é). In newer
+@strong{MySQL} versions @code{LIKE} works just like the other comparison
+operators.
+
+If you want a column always to be treated in case-sensitive fashion,
+declare it as @code{BINARY}. @xref{CREATE TABLE, , @code{CREATE TABLE}}.
+
+If you are using Chinese data in the so-called big5 encoding, you want to
+make all character columns @code{BINARY}. This works because the sorting
+order of big5 encoding characters is based on the order of ASCII codes.
+
+@cindex @code{NULL} values vs. empty values
+@tindex NULL
+@node Problems with NULL, Problems with alias, Case sensitivity, Problems
+@section Problems with @code{NULL} values
+
+The concept of the @code{NULL} value is a common source of confusion for
+newcomers to SQL, who often think that @code{NULL} is the same thing as an
+empty string @code{''}. This is not the case! For example, the following
+statements are completely different:
+
+@example
+mysql> INSERT INTO my_table (phone) VALUES (NULL);
+mysql> INSERT INTO my_table (phone) VALUES ("");
+@end example
+
+Both statements insert a value into the @code{phone} column, but the first
+inserts a @code{NULL} value and the second inserts an empty string. The
+meaning of the first can be regarded as ``phone number is not known'' and the
+meaning of the second can be regarded as ``she has no phone''.
+
+In SQL, the @code{NULL} value is always false in comparison to any
+other value, even @code{NULL}. An expression that contains @code{NULL}
+always produces a @code{NULL} value unless otherwise indicated in
+the documentation for the operators and functions involved in the
+expression. All columns in the following example return @code{NULL}:
+
+@example
+mysql> SELECT NULL,1+NULL,CONCAT('Invisible',NULL);
+@end example
+
+If you want to search for column values that are @code{NULL}, you
+cannot use the @code{=NULL} test. The following statement returns no
+rows, because @code{expr = NULL} is FALSE, for any expression:
+
+@example
+mysql> SELECT * FROM my_table WHERE phone = NULL;
+@end example
+
+To look for @code{NULL} values, you must use the @code{IS NULL} test.
+The following shows how to find the @code{NULL} phone number and the
+empty phone number:
+
+@example
+mysql> SELECT * FROM my_table WHERE phone IS NULL;
+mysql> SELECT * FROM my_table WHERE phone = "";
+@end example
+
+In @strong{MySQL}, as in many other SQL servers, you can't index
+columns that can have @code{NULL} values. You must declare such columns
+@code{NOT NULL}. Conversely, you cannot insert @code{NULL} into an indexed
+column.
+
+@findex LOAD DATA INFILE
+When reading data with @code{LOAD DATA INFILE}, empty columns are updated
+with @code{''}. If you want a @code{NULL} value in a column, you should use
+@code{\N} in the text file. The literal word @code{'NULL'} may also be used
+under some circumstances.
+@xref{LOAD DATA, , @code{LOAD DATA}}.
+
+When using @code{ORDER BY}, @code{NULL} values are presented first. If you
+sort in descending order using @code{DESC}, @code{NULL} values are presented
+last. When using @code{GROUP BY}, all @code{NULL} values are regarded as
+equal.
+
+To help with @code{NULL} handling, you can use the @code{IS NULL} and
+@code{IS NOT NULL} operators and the @code{IFNULL()} function.
+
+@cindex @code{TIMESTAMP}, and @code{NULL} values
+@cindex @code{AUTO_INCREMENT}, and @code{NULL} values
+@cindex @code{NULL} values, and @code{TIMESTAMP} columns
+@cindex @code{NULL} values, and @code{AUTO_INCREMENT} columns
+For some column types, @code{NULL} values are handled specially. If you
+insert @code{NULL} into the first @code{TIMESTAMP} column of a table, the
+current date and time is inserted. If you insert @code{NULL} into an
+@code{AUTO_INCREMENT} column, the next number in the sequence is inserted.
+
+@tindex alias
+@node Problems with alias, Deleting from related tables, Problems with NULL, Problems
+@section Problems with @code{alias}
+
+You can use an alias to refer to a column in the @code{GROUP BY},
+@code{ORDER BY} or in the @code{HAVING} part. Aliases can also be used
+to give columns more better names:
+
+@example
+SELECT SQRT(a*b) as rt FROM table_name GROUP BY rt HAVING rt > 0;
+SELECT id,COUNT(*) AS cnt FROM table_name GROUP BY id HAVING cnt > 0;
+SELECT id AS "Customer identity" FROM table_name;
+@end example
+
+Note that you ANSI SQL doesn't allow you to refer to an alias in a
+@code{WHERE} clause. This is because when the @code{WHERE} code is
+executed the column value may not yet be determinated. For example the
+following query is @strong{illegal}:
+
+@example
+SELECT id,COUNT(*) AS cnt FROM table_name WHERE cnt > 0 GROUP BY id;
+@end example
+
+The @code{WHERE} statement is executed to determinate which rows should
+be included in the @code{GROUP BY} part while @code{HAVING} is used to
+decide which rows from the result set should be used.
+
+@node Deleting from related tables, No matching rows, Problems with alias, Problems
+@section Deleting rows from related tables
+
+As @strong{MySQL} doesn't support sub-selects or use of more than one table
+in the @code{DELETE} statement, you should use the following approach to
+delete rows from 2 related tables:
+
+@enumerate
+@item
+@code{SELECT} the rows based on some @code{WHERE} condition in the main table.
+@item
+@code{DELETE} the rows in the main table based on the same condition.
+@item
+@code{DELETE FROM related_table WHERE related_column IN (selected_rows)}
+@end enumerate
+
+If the total number of characters in the query with
+@code{related_column} is more than 1,048,576 (the default value of
+@code{max_allowed_packet}, you should split it into smaller parts and
+execute multiple @code{DELETE} statements. You will probably get the
+fastest @code{DELETE} by only deleting 100-1000 @code{related_column}
+id's per query if the @code{related_column} is an index. If the
+@code{related_column} isn't an index, the speed is independent of the
+number of arguments in the @code{IN} clause.
+
+@node No matching rows, ALTER TABLE problems, Deleting from related tables, Problems
+@section Solving problems with no matching rows
+
+If you have a complicated query with many tables that doesn't return any
+rows, you should use the following procedure to find out what is wrong
+with your query:
+
+@enumerate
+@item
+Test the query with @code{EXPLAIN} and check if you can find something that is
+obviously wrong. @xref{EXPLAIN, , @code{EXPLAIN}}.
+
+@item
+Select only those fields that are used in the @code{WHERE} clause.
+
+@item
+Remove one table at a time from the query until it returns some rows.
+If the tables are big, it's a good idea to use @code{LIMIT 10} with the query.
+
+@item
+Do a @code{SELECT} for the column that should have matched a row,
+against the table that was last removed from the query.
+
+@item
+If you are comparing @code{FLOAT} or @code{DOUBLE} columns with numbers that
+have decimals, you can't use @code{=}! This problem is common in most
+computer languages because floating point values are not exact values.
+
+@example
+mysql> SELECT * FROM table_name WHERE float_column=3.5;
+ ->
+mysql> SELECT * FROM table_name WHERE float_column between 3.45 and 3.55;
+@end example
+
+In most cases, changing the @code{FLOAT} to a @code{DOUBLE} will fix this!
+
+@item
+If you still can't figure out what's wrong, create a minimal test that can
+be run with @code{mysql test < query.sql} that shows your problems.
+You can create a test file with @code{mysqldump --quick database tables > query.sql}. Open the file in an editor, remove some insert lines (if there are
+too many of these) and add your select statement at the end of the file.
+
+Test that you still have your problem by doing:
+
+@example
+shell> mysqladmin create test2
+shell> mysql test2 < query.sql
+@end example
+
+Post the test file using @code{mysqlbug} to @email{mysql@@lists.mysql.com}.
+@end enumerate
+
+@node ALTER TABLE problems, Change column order, No matching rows, Problems
+@section Problems with @code{ALTER TABLE}.
+
+If @code{ALTER TABLE} dies with an error like this:
+
+@example
+Error on rename of './database/name.frm' to './database/B-a.frm' (Errcode: 17)
+@end example
+
+The problem may be that @strong{MySQL} has crashed in a previous @code{ALTER
+TABLE} and there is an old table named @file{A-something} or
+@file{B-something} lying around. In this case, go to the @strong{MySQL} data
+directory and delete all files that have names starting with @code{A-} or
+@code{B-}. (You may want to move them elsewhere instead of deleting them).
+
+@code{ALTER TABLE} works the following way:
+
+@itemize @bullet
+@item Create a new table named @file{A-xxx} with the requested changes.
+@item All rows from the old table are copied to @file{A-xxx}.
+@item The old table is renamed @file{B-xxx}.
+@item @file{A-xxx} is renamed to your old table name.
+@item @file{B-xxx} is deleted.
+@end itemize
+
+If something goes wrong with the renaming operation, @strong{MySQL} tries to
+undo the changes. If something goes seriously wrong (this shouldn't happen,
+of course), @strong{MySQL} may leave the old table as @file{B-xxx} but a
+simple rename should get your data back.
+
+@node Change column order, , ALTER TABLE problems, Problems
+@section How to change the order of columns in a table
+
+The whole point of SQL is to abstract the application from the data
+storage format. You should always specify the order in wish you wish to
+retrieve your data. For example:
+
+@example
+SELECT col_name1, col_name2, col_name3 FROM tbl_name;
+@end example
+
+will return columns in the order @code{col_name1}, @code{col_name2}, @code{col_name3}, whereas:
+
+@example
+SELECT col_name1, col_name3, col_name2 FROM tbl_name;
+@end example
+
+will return columns in the order @code{col_name1}, @code{col_name3}, @code{col_name2}.
+
+You should @strong{NEVER}, in an application, use @code{SELECT *} and
+retrieve the columns based on their position, because the order in which columns are
+returned @strong{CANNOT} be guaranteed over time; A simple change to
+your database may cause your application to fail rather dramatically.
+
+If you want to change the order of columns anyway, you can do it as follows:
+
+@enumerate
+@item
+Create a new table with the columns in the right order.
+@item
+Execute
+@code{INSERT INTO new_table SELECT fields-in-new_table-order FROM old_table}.
+@item
+Drop or rename @code{old_table}
+@item
+@code{ALTER TABLE new_table RENAME old_table}
+@end enumerate
+
+@node Common problems, Clients, Problems, Top
+@chapter Solving some common problems with MySQL
+
+@cindex Replication
+@menu
+* Log Replication:: Database replication with update log
+* Backup:: Database backups
+* Update log:: The update log
+* Multiple servers:: Running multiple @strong{MySQL} servers on the same machine
+@end menu
+
+@cindex Database replication
+@cindex Replication, database
+@node Log Replication, Backup, Common problems, Common problems
+@section Database replication with update log
+
+
+Now that master-slave internal replication is available starting in 3.23.15,
+this is the recommended way. However, it is still possible to replicate a database by
+using the update
+log. @xref{Update log}. This requires one database that acts as a master
+(to which data changes are made) and one or more other databases that act
+as slaves. To update a slave, just run @code{mysql < update_log}.
+Supply host, user and password options that are appropriate for the slave
+database, and use the update log from the master database as input.
+
+If you never delete anything from a table, you can use a @code{TIMESTAMP}
+column to find out which rows have been inserted or changed in the table
+since the last replication (by comparing to the time when you did the
+replication last time) and only copy these rows to the mirror.
+
+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 conflicts when the same data have been changed in
+both ends. You probably want to keep the old version to help with
+deciding what has been updated.
+
+Because replication in this case is done with SQL statements, you should not
+use the following functions in statements that update the database; they may
+not return the same value as in the original database:
+
+@itemize @bullet
+@item @code{DATABASE()}
+@item @code{GET_LOCK()} and @code{RELEASE_LOCK()}
+@item @code{RAND()}
+@item @code{USER()}, @code{SYSTEM_USER()} or @code{SESSION_USER()}
+@item @code{VERSION()}, @code{CONNECT_ID()}
+@end itemize
+
+All time functions are safe to use, as the timestamp is sent to the
+mirror if needed. @code{LAST_INSERT_ID()} is also safe to use.
+
+@cindex Backups
+@node Backup, Update log, Log Replication, Common problems
+@section Database backups
+
+Because @strong{MySQL} tables are stored as files, it is easy to do a
+backup. To get a consistent backup, do a @code{LOCK TABLES} on the
+relevant tables. @xref{LOCK TABLES, , @code{LOCK TABLES}}. You only need a
+read lock; this allows other threads to continue to query the tables while
+you are making a copy of the files in the database directory. If you want to
+make a SQL level backup of a table, you can use @code{SELECT INTO OUTFILE}.
+
+Another way to backup a database is to use the @code{mysqldump} program:
+@xref{mysqldump}.
+
+@enumerate
+@item
+Do a full backup of your databases:
+
+@example
+shell> mysqldump --tab=/path/to/some/dir --opt --full
+@end example
+
+You can also simply copy all table files (@file{*.frm}, @file{*.MYD} and
+@file{*.MYI} files), as long as the server isn't updating anything.
+The script @code{mysqlhotcopy} does use this method.
+
+@item
+@cindex Log file, names
+Stop @code{mysqld} if it's running, then start it with the
+@code{--log-update[=file_name]} option. @xref{Update log}. The update
+log file(s) provide you with the information you need to replicate
+changes to the database that are made subsequent to the point at which
+you executed @code{mysqldump}.
+@end enumerate
+
+If you have to restore something, try to recover your tables using
+@code{myisamchk -r} first. That should work in 99.9% of all cases. If
+@code{myisamchk} fails, try the following procedure:
+(This will only work if you have started @strong{MySQL} with
+@code{--log-update}. @xref{Update log}.)
+
+@enumerate
+@item
+Restore the original @code{mysqldump} backup.
+@item
+Execute the following command to re-run the updates in the update logs:
+@example
+shell> ls -1 -t -r hostname.[0-9]* | xargs cat | mysql
+@end example
+@end enumerate
+
+@code{ls} is used to get all the update log files in the right order.
+
+You can also do selective backups with @code{SELECT * INTO OUTFILE 'file_name'
+FROM tbl_name} and restore with @code{LOAD DATA INFILE 'file_name' REPLACE
+...} To avoid duplicate records, you need a @code{PRIMARY KEY} or a
+@code{UNIQUE} key in the table. The @code{REPLACE} keyword causes old records
+to be replaced with new ones when a new record duplicates an old record on
+a unique key value.
+
+@cindex Update log
+@node Update log, Multiple servers, Backup, Common problems
+@section The update log
+
+When started with the @code{--log-update[=file_name]} option,
+@code{mysqld} writes a log file containing all SQL commands that update
+data. If no file name is given, it defaults to the name of the host
+machine, If file name is given, but it doesn't contain a path the file
+is written in the data directory. If file_name doesn't have an
+extension, @code{mysqld} will create log file names of type
+@code{file_name.#}, where @code{#} is a number that is incremented each
+time you execute @code{mysqladmin refresh} or @code{mysqladmin
+flush-logs}, the @code{FLUSH LOGS} statement, or restart the server.
+
+@strong{Note:} For the above scheme to work, you should NOT create
+own files with the same file name as the update log + some extensions
+that may be regarded as a number, in the directory used by the update log!
+
+If you use the @code{--log} or @code{-l} options, @code{mysqld} writes a
+general log with a filename of @file{hostname.log}, and restarts and
+refreshes do not cause a new log file to be generated (although it is closed
+and reopened). In this case you can copy it (on Unix) by doing:
+
+@example
+mv hostname.log hostname-old.log
+mysqladmin flush-logs
+cp hostname-old.log to-backup-directory
+rm hostname-old.log
+@end example
+
+By default, the @code{mysql.server} script starts the @strong{MySQL}
+server with the @code{-l} option. If you need better performance when
+you start using @strong{MySQL} in a production environment, you can
+remove the @code{-l} option from @code{mysql.server} or change it to
+@code{--log-update}.
+
+Update logging is smart because it logs only statements that really update
+data. So an @code{UPDATE} or a @code{DELETE} with a @code{WHERE} that finds no
+rows is not written to the log. It even skips @code{UPDATE} statements that
+set a column to the value it already has.
+
+If you want to update a database from update log files, you could do the
+following (assuming your update logs have names of the form
+@file{file_name.###}):
+
+@example
+shell> ls -1 -t -r file_name.[0-9]* | xargs cat | mysql
+@end example
+
+@code{ls} is used to get all the log files in the right order.
+
+This can be useful if you have to revert to backup files after a crash
+and you want to redo the updates that occurred between the time of the backup
+and the crash.
+
+@cindex Database replication
+@cindex Replication, database
+@cindex Database mirroring
+@cindex Mirroring, database
+You can also use the update logs when you have a mirrored database on
+another host and you want to replicate the changes that have been made
+to the master database. @xref{Log Replication}.
+
+@cindex Multiple servers
+@node Multiple servers, , Update log, Common problems
+@section Running multiple MySQL servers on the same machine
+
+There are circumstances when you might want to run multiple servers on the same
+machine. For example, you might want to test a new @strong{MySQL} release
+while leaving your existing production setup undisturbed. Or you might
+be an Internet service provider that wants to provide independent
+@strong{MySQL} installations for different customers.
+
+If you want to run multiple servers, the easiest way is to compile the servers
+with different TCP/IP ports and socket files so they are not
+both listening to the same TCP/IP port or socket file.
+
+Assume an existing server is configured for the default port number and
+socket file. Then configure the new server with a @code{configure} command
+something like this:
+
+@example
+shell> ./configure --with-tcp-port=port_number \
+ --with-unix-socket=file_name \
+ --prefix=/usr/local/mysql-3.22.9
+@end example
+
+Here @code{port_number} and @code{file_name} should be different than the
+default port number and socket file pathname, and the @code{--prefix} value
+should specify an installation directory different than the one under which
+the existing @strong{MySQL} installation is located.
+
+You can check the socket and port used by any currently-executing
+@strong{MySQL} server with this command:
+
+@example
+shell> mysqladmin -h hostname --port=port_number variables
+@end example
+
+If you have a @strong{MySQL} server running on the port you used, you will
+get a list of some of the most important configurable variables in
+@strong{MySQL}, including the socket name.
+
+You should also edit the initialization script for your machine (probably
+@file{mysql.server}) to start and kill multiple @code{mysqld} servers.
+
+You don't have to recompile a new @strong{MySQL} server just to start with
+a different port and socket. You can change the port and socket to be used
+by specifying them at runtime as options to @code{safe_mysqld}:
+
+@example
+shell> /path/to/safe_mysqld --socket=file_name --port=port_number
+@end example
+
+If you run the new server on the same database directory as another server
+with logging enabled, you should also specify the name of the log files
+to @code{safe_mysqld} with @code{--log} and @code{--log-update}. Otherwise,
+both servers may be trying to write to the same log file.
+
+@strong{Warning}: Normally you should never have two servers that update
+data in the same database! If your OS doesn't support fault-free system
+locking, this may lead to unpleasant surprises!
+
+If you want to use another database directory for the second server, you
+can use the @code{--datadir=path} option to @code{safe_mysqld}.
+
+When you want to connect to a @strong{MySQL} server that is running with
+a different port than the port that is compiled into your client, you
+can use one of the following methods:
+
+@itemize @bullet
+@item
+Start the client with @code{--host 'hostname' --port=port_numer} or
+@code{[--host localhost] --socket=file_name}.
+
+@item
+In your C or Perl programs, you can give the port and socket arguments
+when connecting to the @strong{MySQL} server.
+
+@item
+@tindex MYSQL_UNIX_PORT environment variable
+@tindex MYSQL_TCP_PORT environment variable
+@tindex Environment variable, MYSQL_UNIX_PORT
+@tindex Environment variable, MYSQL_TCP_PORT
+Set the @code{MYSQL_UNIX_PORT} and @code{MYSQL_TCP_PORT} environment variables
+to point to the Unix socket and TCP/IP port before you start your clients.
+If you normally use a specific socket or port, you should place commands
+to set these environment variables in your @file{.login} file.
+@xref{Environment variables}. @xref{Programs}.
+
+@item
+@tindex .my.cnf file
+Specify the default socket and TCP/IP port in the @file{.my.cnf} file in your
+home directory. @xref{Option files}.
+@end itemize
+
+@node Clients, Comparisons, Common problems, Top
+@chapter MySQL client tools and APIs
+
+@menu
+* C:: @strong{MySQL} C API
+* C API datatypes:: C API datatypes
+* C API function overview:: C API function Overview
+* C API functions:: C API function descriptions
+* Perl:: @strong{MySQL} Perl API
+* Eiffel:: @strong{MySQL} Eiffel wrapper
+* Java:: @strong{MySQL} Java connectivity (JDBC)
+* PHP:: @strong{MySQL} PHP API
+* Cplusplus:: @strong{MySQL} C++ APIs
+* Python:: @strong{MySQL} Python APIs
+* Tcl:: @strong{MySQL} Tcl APIs
+@end menu
+
+@node C, C API datatypes, Clients, Clients
+@section MySQL C API
+
+The C API code is distributed with @strong{MySQL}. It is included in the
+@code{mysqlclient} library and allows C programs to access a database.
+
+Many of the clients in the @strong{MySQL} source distribution are
+written in C. If you are looking for examples that demonstrate how to
+use the C API, take a look at these clients. You can find these in the
+@code{clients} directory in the @strong{MySQL} source distribution.
+
+Most of the other client APIs (all except Java) use the @code{mysqlclient}
+library to communicate with the @strong{MySQL} server. This means that, for
+example, you can take advantage of many of the same environment variables
+that are used by other client programs, because they are referenced from the
+library. See @ref{Programs}, for a list of these variables.
+
+The client has a maximum communication buffer size. The size of the buffer
+that is allocated initially (16K bytes) is automatically increased up to the
+maximum size (the default maximum is 24M). Because buffer sizes are increased
+only as demand warrants, simply increasing the default maximum limit does not
+in itself cause more resources to be used. This size check is mostly a check
+for erroneous queries and communication packets.
+
+The communication buffer must be large enough to contain a single SQL
+statement (for client-to-server traffic) and one row of returned data (for
+server-to-client traffic). Each thread's communication buffer is dynamically
+enlarged to handle any query or row up to the maximum limit. For example, if
+you have @code{BLOB} values that contain up to 16M of data, you must have a
+communication buffer limit of at least 16M (in both server and client). The
+client's default maximum is 24M, but the default maximum in the server is
+1M. You can increase this by changing the value of the
+@code{max_allowed_packet} parameter when the server is started. @xref{Server
+parameters}.
+
+The @strong{MySQL} server shrinks each communication buffer to
+@code{net_buffer_length} bytes after each query. For clients, the size of
+the buffer associated with a connection is not decreased until the connection
+is closed, at which time client memory is reclaimed.
+
+If you are programming with threads, you should compile the
+@strong{MySQL} C API with @code{--with-thread-safe-client}. This will make
+the C API thread safe per connection. You can let two threads share the same
+connection as long as you do the following:
+
+@table @asis
+@item
+Two threads can't send a query to the @strong{MySQL} at the same time on
+the same connection. In particular you have to ensure that between a
+@code{mysql_query()} and @code{mysql_store_result()} no other thread is using
+the same connection.
+@item
+Many threads can access different result sets that are retrieved with
+@code{mysql_store_result()}.
+@item
+If you use @code{mysql_use_result}, you have to ensure that no other thread
+is asking anything on the same connection until the result set is closed.
+@end table
+
+@node C API datatypes, C API function overview, C, Clients
+@section C API datatypes
+@table @code
+
+@tindex MYSQL C type
+@item MYSQL
+This structure represents a handle to one database connection. It is
+used for almost all @strong{MySQL} functions.
+
+@tindex MYSQL_RES C type
+@item MYSQL_RES
+This structure represents the result of a query that returns rows
+(@code{SELECT}, @code{SHOW}, @code{DESCRIBE}, @code{EXPLAIN}). The
+information returned from a query is called the @emph{result set} in the
+remainder of this section.
+
+@tindex MYSQL_ROW C type
+@item MYSQL_ROW
+This is a type-safe representation of one row of data. It is currently
+implemented as an array of counted byte strings. (You cannot treat these as
+null-terminated strings if field values may contain binary data, because such
+values may contain null bytes internally.) Rows are obtained by calling
+@code{mysql_fetch_row()}.
+
+@tindex MYSQL_FIELD C type
+@item MYSQL_FIELD
+This structure contains information about a field, such as the field's
+name, type and size. Its members are described in more detail below.
+You may obtain the @code{MYSQL_FIELD} structures for each field by
+calling @code{mysql_fetch_field()} repeatedly. Field values are not part of
+this structure; they are contained in a @code{MYSQL_ROW} structure.
+
+
+@tindex MYSQL_FIELD_OFFSET C type
+@item MYSQL_FIELD_OFFSET
+This is a type-safe representation of an offset into a @strong{MySQL} field
+list. (Used by @code{mysql_field_seek()}.) Offsets are field numbers
+within a row, beginning at zero.
+
+@tindex my_ulonglong C type
+@tindex my_ulonglong values, printing
+@item my_ulonglong
+The type used for the number of rows and for @code{mysql_affected_rows()},
+@code{mysql_num_rows()} and @code{mysql_insert_id()}. This type provides a
+range of @code{0} to @code{1.84e19}.
+
+On some systems, attempting to print a value of type @code{my_ulonglong}
+will not work. To print such a value, convert it to @code{unsigned long}
+and use a @code{%lu} print format. Example:
+@example
+printf (Number of rows: %lu\n", (unsigned long) mysql_num_rows(result));
+@end example
+@end table
+
+@noindent
+The @code{MYSQL_FIELD} structure contains the members listed below:
+
+@table @code
+@item char * name
+The name of the field, as a null-terminated string.
+
+@item char * table
+The name of the table containing this field, if it isn't a calculated field.
+For calculated fields, the @code{table} value is an empty string.
+
+@item char * def
+The default value of this field, as a null-terminated string. This is set
+only if you use @code{mysql_list_fields()}.
+
+@item enum enum_field_types type
+The type of the field.
+The @code{type} value may be one of the following:
+
+@multitable @columnfractions .3 .55
+@item @strong{Type value} @tab @strong{Type meaning}
+@item @code{FIELD_TYPE_TINY} @tab @code{TINYINT} field
+@item @code{FIELD_TYPE_SHORT} @tab @code{SMALLINT} field
+@item @code{FIELD_TYPE_LONG} @tab @code{INTEGER} field
+@item @code{FIELD_TYPE_INT24} @tab @code{MEDIUMINT} field
+@item @code{FIELD_TYPE_LONGLONG} @tab @code{BIGINT} field
+@item @code{FIELD_TYPE_DECIMAL} @tab @code{DECIMAL} or @code{NUMERIC} field
+@item @code{FIELD_TYPE_FLOAT} @tab @code{FLOAT} field
+@item @code{FIELD_TYPE_DOUBLE} @tab @code{DOUBLE} or @code{REAL} field
+@item @code{FIELD_TYPE_TIMESTAMP} @tab @code{TIMESTAMP} field
+@item @code{FIELD_TYPE_DATE} @tab @code{DATE} field
+@item @code{FIELD_TYPE_TIME} @tab @code{TIME} field
+@item @code{FIELD_TYPE_DATETIME} @tab @code{DATETIME} field
+@item @code{FIELD_TYPE_YEAR} @tab @code{YEAR} field
+@item @code{FIELD_TYPE_STRING} @tab String (@code{CHAR} or @code{VARCHAR}) field
+@item @code{FIELD_TYPE_BLOB} @tab @code{BLOB} or @code{TEXT} field (use @code{max_length} to determine the maximum length)
+@item @code{FIELD_TYPE_SET} @tab @code{SET} field
+@item @code{FIELD_TYPE_ENUM} @tab @code{ENUM} field
+@item @code{FIELD_TYPE_NULL} @tab @code{NULL}-type field
+@item @code{FIELD_TYPE_CHAR} @tab Deprecated; use @code{FIELD_TYPE_TINY} instead
+@end multitable
+
+You can use the @code{IS_NUM()} macro to test whether or not a field has a
+numeric type. Pass the @code{type} value to @code{IS_NUM()} and it
+will evaluate to TRUE if the field is numeric:
+
+@example
+if (IS_NUM(field->type))
+ printf("Field is numeric\n");
+@end example
+
+@item unsigned int length
+The width of the field, as specified in the table definition.
+
+@item unsigned int max_length
+The maximum width of the field for the result set (the length of the longest
+field value for the rows actually in the result set). If you use
+@code{mysql_store_result()} or @code{mysql_list_fields()}, this contains the
+maximum length for the field. If you use @code{mysql_use_result()}, the
+value of this variable is zero.
+
+@item unsigned int flags
+Different bit-flags for the field. The @code{flags} value may have zero
+or more of the following bits set:
+
+@multitable @columnfractions .3 .55
+@item @strong{Flag value} @tab @strong{Flag meaning}
+@item @code{NOT_NULL_FLAG} @tab Field can't be @code{NULL}
+@item @code{PRI_KEY_FLAG} @tab Field is part of a primary key
+@item @code{UNIQUE_KEY_FLAG} @tab Field is part of a unique key
+@item @code{MULTIPLE_KEY_FLAG} @tab Field is part of a non-unique key.
+@item @code{UNSIGNED_FLAG} @tab Field has the @code{UNSIGNED} attribute
+@item @code{ZEROFILL_FLAG} @tab Field has the @code{ZEROFILL} attribute
+@item @code{BINARY_FLAG} @tab Field has the @code{BINARY} attribute
+@item @code{AUTO_INCREMENT_FLAG} @tab Field has the @code{AUTO_INCREMENT} attribute
+@item @code{ENUM_FLAG} @tab Field is an @code{ENUM} (deprecated)
+@item @code{BLOB_FLAG} @tab Field is a @code{BLOB} or @code{TEXT} (deprecated)
+@item @code{TIMESTAMP_FLAG} @tab Field is a @code{TIMESTAMP} (deprecated)
+@end multitable
+
+Use of the @code{BLOB_FLAG}, @code{ENUM_FLAG} and @code{TIMESTAMP_FLAG} flags
+is deprecated because they indicate the type of a field rather than an
+attribute of its type. It is preferable to test @code{field->type} against
+@code{FIELD_TYPE_BLOB}, @code{FIELD_TYPE_ENUM} or @code{FIELD_TYPE_TIMESTAMP}
+instead.
+
+@noindent
+The example below illustrates a typical use of the @code{flags} value:
+
+@example
+if (field->flags & NOT_NULL_FLAG)
+ printf("Field can't be null\n");
+@end example
+
+You may use the following convenience macros to determine the boolean
+status of the @code{flags} value:
+
+@multitable @columnfractions .3 .5
+@item @code{IS_NOT_NULL(flags)} @tab True if this field is defined as @code{NOT NULL}
+@item @code{IS_PRI_KEY(flags)} @tab True if this field is a primary key
+@item @code{IS_BLOB(flags)} @tab True if this field is a @code{BLOB} or @code{TEXT} (deprecated; test @code{field->type} instead)
+@end multitable
+
+@item unsigned int decimals
+The number of decimals for numeric fields.
+@end table
+
+@node C API function overview, C API functions, C API datatypes, Clients
+@section C API function overview
+
+The functions available in the C API are listed below and are described in
+greater detail in the next section.
+@xref{C API functions}.
+
+@multitable @columnfractions .3 .7
+@item @strong{mysql_affected_rows()} @tab
+Returns the number of rows affected by the last @code{UPDATE}, @code{DELETE} or
+@code{INSERT} query.
+
+@item @strong{mysql_close()} @tab
+Closes a server connection.
+
+@item @strong{mysql_connect()} @tab
+Connects to a @strong{MySQL} server. This function is deprecated; use
+@code{mysql_real_connect()} instead.
+
+@item @strong{mysql_change_user()} @tab
+Change user and database on an open connection.
+
+@item @code{mysql_character_set_name()} @tab
+Returns the name of the default character set for the connection.
+
+@item @strong{mysql_create_db()} @tab
+Creates a database. This function is deprecated; use the SQL command
+@code{CREATE DATABASE} instead.
+
+@item @strong{mysql_data_seek()} @tab
+Seeks to an arbitrary row in a query result set.
+
+@item @strong{mysql_debug()} @tab
+Does a @code{DBUG_PUSH} with the given string.
+
+@item @strong{mysql_drop_db()} @tab
+Drops a database. This function is deprecated; use the SQL command
+@code{DROP DATABASE} instead.
+
+@item @strong{mysql_dump_debug_info()} @tab
+Makes the server write debug information to the log.
+
+@item @strong{mysql_eof()} @tab
+Determines whether or not the last row of a result set has been read.
+This function is deprecated; @code{mysql_errno()} or @code{mysql_error()}
+may be used instead.
+
+@item @strong{mysql_errno()} @tab
+Returns the error number for the most recently invoked @strong{MySQL} function.
+
+@item @strong{mysql_error()} @tab
+Returns the error message for the most recently invoked @strong{MySQL} function.
+
+@item @strong{mysql_real_escape_string()} @tab
+Escapes special characters in a string for use in a SQL statement taking
+into account the current charset of the connection.
+
+@item @strong{mysql_escape_string()} @tab
+Escapes special characters in a string for use in a SQL statement.
+
+@item @strong{mysql_fetch_field()} @tab
+Returns the type of the next table field.
+
+@item @strong{mysql_fetch_field_direct()} @tab
+Returns the type of a table field, given a field number.
+
+@item @strong{mysql_fetch_fields()} @tab
+Returns an array of all field structures.
+
+@item @strong{mysql_fetch_lengths()} @tab
+Returns the lengths of all columns in the current row.
+
+@item @strong{mysql_fetch_row()} @tab
+Fetches the next row from the result set.
+
+@item @strong{mysql_field_seek()} @tab
+Puts the column cursor on a specified column.
+
+@item @strong{mysql_field_count()} @tab
+Returns the number of result columns for the most recent query.
+
+@item @strong{mysql_field_tell()} @tab
+Returns the position of the field cursor used for the last
+@code{mysql_fetch_field()}.
+
+@item @strong{mysql_free_result()} @tab
+Frees memory used by a result set.
+
+@item @strong{mysql_get_client_info()} @tab
+Returns client version information.
+
+@item @strong{mysql_get_host_info()} @tab
+Returns a string describing the connection.
+
+@item @strong{mysql_get_proto_info()} @tab
+Returns the protocol version used by the connection.
+
+@item @strong{mysql_get_server_info()} @tab
+Returns the server version number.
+
+@item @strong{mysql_info()} @tab
+Returns information about the most recently executed query.
+
+@item @strong{mysql_init()} @tab
+Gets or initializes a @code{MYSQL} structure.
+
+@item @strong{mysql_insert_id()} @tab
+Returns the ID generated for an @code{AUTO_INCREMENT} column by the previous
+query.
+
+@item @strong{mysql_kill()} @tab
+Kill a given thread.
+
+@item @strong{mysql_list_dbs()} @tab
+Returns database names matching a simple regular expression.
+
+@item @strong{mysql_list_fields()} @tab
+Returns field names matching a simple regular expression.
+
+@item @strong{mysql_list_processes()} @tab
+Returns a list of the current server threads.
+
+@item @strong{mysql_list_tables()} @tab
+Returns table names matching a simple regular expression.
+
+@item @strong{mysql_num_fields()} @tab
+Returns the number of columns in a result set.
+
+@item @strong{mysql_num_rows()} @tab
+Returns the number of rows in a result set.
+
+@item @strong{mysql_options()} @tab
+Set connect options for @code{mysql_connect()}.
+
+@item @strong{mysql_ping()} @tab
+Checks whether or not the connection to the server is working, reconnecting
+as necessary.
+
+@item @strong{mysql_query()} @tab
+Executes a SQL query specified as a null-terminated string.
+
+@item @strong{mysql_real_connect()} @tab
+Connects to a @strong{MySQL} server.
+
+@item @strong{mysql_real_query()} @tab
+Executes a SQL query specified as a counted string.
+
+@item @strong{mysql_reload()} @tab
+Tells the server to reload the grant tables.
+
+@item @strong{mysql_row_seek()} @tab
+Seeks to a row in a result set, using value returned from
+@code{mysql_row_tell()}.
+
+@item @strong{mysql_row_tell()} @tab
+Returns the row cursor position.
+
+@item @strong{mysql_select_db()} @tab
+Selects a database.
+
+@item @strong{mysql_shutdown()} @tab
+Shuts down the database server.
+
+@item @strong{mysql_start_slave()} @tab
+Starts slave replication thread
+
+@item @strong{mysql_stat()} @tab
+Returns the server status as a string.
+
+@item @strong{mysql_store_result()} @tab
+Retrieves a complete result set to the client.
+
+@item @strong{mysql_stop_slave()} @tab
+Stops slave replication thread
+
+@item @strong{mysql_thread_id()} @tab
+Returns the current thread ID.
+
+@item @strong{mysql_thread_save()} @tab
+Returns 1 if the clients are compiled as threadsafe.
+
+@item @strong{mysql_use_result()} @tab
+Initiates a row-by-row result set retrieval.
+@end multitable
+
+To connect to the server, call @code{mysql_init()} to initialize a
+connection handler, then call @code{mysql_real_connect()} with that
+handler (along with other information such as the hostname, user name
+and password). Upon connection, @code{mysql_real_connect()} sets the
+@code{reconnect} flag (part of the MYSQL structure) to a value of
+@code{1}. This flag indicates, in the event that a query cannot be
+performed because of a lost connection, to try reconnecting to the
+server before giving up. When you are done with the connection, call
+@code{mysql_close()} to terminate it.
+
+While a connection is active, the client may send SQL queries to the server
+using @code{mysql_query()} or @code{mysql_real_query()}. The difference
+between the two is that @code{mysql_query()} expects the query to be
+specified as a null-terminated string whereas @code{mysql_real_query()}
+expects a counted string. If the string contains binary data (which may
+include null bytes), you must use @code{mysql_real_query()}.
+
+For each non-@code{SELECT} query (e.g., @code{INSERT}, @code{UPDATE},
+@code{DELETE}), you can found out how many rows were affected (changed)
+by calling @code{mysql_affected_rows()}.
+
+For @code{SELECT} queries, you retrieve the selected rows as a result set.
+(Note that some statements are @code{SELECT}-like in that they return rows.
+These include @code{SHOW}, @code{DESCRIBE} and @code{EXPLAIN}. They should
+be treated the same way as @code{SELECT} statements.)
+
+There are two ways for a client to process result sets. One way is to
+retrieve the entire result set all at once by calling
+@code{mysql_store_result()}. This function acquires from the server all the
+rows returned by the query and stores them in the client. The second way is
+for the client to initiate a row-by-row result set retrieval by calling
+@code{mysql_use_result()}. This function initializes the retrieval, but does
+not actually get any rows from the server.
+
+In both cases, you access rows by calling @code{mysql_fetch_row()}. With
+@code{mysql_store_result()}, @code{mysql_fetch_row()} accesses rows that have
+already been fetched from the server. With @code{mysql_use_result()},
+@code{mysql_fetch_row()} actually retrieves the row from the server.
+Information about the size of the data in each row is available by
+calling @code{mysql_fetch_lengths()}.
+
+After you are done with a result set, call @code{mysql_free_result()}
+to free the memory used for it.
+
+The two retrieval mechanisms are complementary. Client programs should
+choose the approach that is most appropriate for their requirements.
+In practice, clients tend to use @code{mysql_store_result()} more
+commonly.
+
+An advantage of @code{mysql_store_result()} is that because the rows have all
+been fetched to the client, you not only can access rows sequentially, you
+can move back and forth in the result set using @code{mysql_data_seek()} or
+@code{mysql_row_seek()} to change the current row position within the result
+set. You can also find out how many rows there are by calling
+@code{mysql_num_rows()}. On the other hand, the memory requirements for
+@code{mysql_store_result()} may be very high for large result sets and you
+are more likely to encounter out-of-memory conditions.
+
+An advantage of @code{mysql_use_result()} is that the client requires less
+memory for the result set because it maintains only one row at a time (and
+because there is less allocation overhead, @code{mysql_use_result()} can be
+faster). Disadvantages are that you must process each row quickly to avoid
+tying up the server, you don't have random access to rows within the result
+set (you can only access rows sequentially), and you don't know how many rows
+are in the result set until you have retrieved them all. Furthermore, you
+@emph{must} retrieve all the rows even if you determine in mid-retrieval that
+you've found the information you were looking for.
+
+The API makes it possible for clients to respond appropriately to
+queries (retrieving rows only as necessary) without knowing whether or
+not the query is a @code{SELECT}. You can do this by calling
+@code{mysql_store_result()} after each @code{mysql_query()} (or
+@code{mysql_real_query()}). If the result set call succeeds, the query
+was a @code{SELECT} and you can read the rows. If the result set call
+fails, call @code{mysql_field_count()} to determine whether or not a
+result was actually to be expected. If @code{mysql_field_count()}
+returns zero, the query returned no data (indicating that it was an
+@code{INSERT}, @code{UPDATE}, @code{DELETE}, etc.), and thus not
+expected to return rows. If @code{mysql_field_count()} is non-zero, the
+query should have returned rows, but didn't. This indicates that the
+query was a @code{SELECT} that failed. See the description for
+@code{mysql_field_count()} for an example of how this can be done.
+
+Both @code{mysql_store_result()} and @code{mysql_use_result()} allow you to
+obtain information about the fields that make up the result set (the number
+of fields, their names and types, etc.). You can access field information
+sequentially within the row by calling @code{mysql_fetch_field()} repeatedly,
+or by field number within the row by calling
+@code{mysql_fetch_field_direct()}. The current field cursor position may be
+changed by calling @code{mysql_field_seek()}. Setting the field cursor
+affects subsequent calls to @code{mysql_fetch_field()}. You can also get
+information for fields all at once by calling @code{mysql_fetch_fields()}.
+
+For detecting and reporting errors, @strong{MySQL} provides access to error
+information by means of the @code{mysql_errno()} and @code{mysql_error()}
+functions. These return the error code or error message for the most
+recently invoked function that can succeed or fail, allowing you to determine
+when an error occurred and what it was.
+
+@node C API functions, Perl, C API function overview, Clients
+@section C API function descriptions
+
+@menu
+* mysql_affected_rows:: @code{mysql_affected_rows()}
+* mysql_close:: @code{mysql_close()}
+* mysql_connect:: @code{mysql_connect()}
+* mysql_change_user:: @code{mysql_change_user()}
+* mysql_character_set_name:: @code{mysql_character_set_name()}
+* mysql_create_db:: @code{mysql_create_db()}
+* mysql_data_seek:: @code{mysql_data_seek()}
+* mysql_debug:: @code{mysql_debug()}
+* mysql_drop_db:: @code{mysql_drop_db()}
+* mysql_dump_debug_info:: @code{mysql_dump_debug_info()}
+* mysql_eof:: @code{mysql_eof()}
+* mysql_errno:: @code{mysql_errno()}
+* mysql_error:: @code{mysql_error()}
+* mysql_escape_string:: @code{mysql_escape_string()}
+* mysql_fetch_field:: @code{mysql_fetch_field()}
+* mysql_fetch_fields:: @code{mysql_fetch_fields()}
+* mysql_fetch_field_direct:: @code{mysql_fetch_field_direct()}
+* mysql_fetch_lengths:: @code{mysql_fetch_lengths()}
+* mysql_fetch_row:: @code{mysql_fetch_row()}
+* mysql_field_count:: @code{mysql_field_count()}
+* mysql_field_seek:: @code{mysql_field_seek()}
+* mysql_field_tell:: @code{mysql_field_tell()}
+* mysql_free_result:: @code{mysql_free_result()}
+* mysql_get_client_info:: @code{mysql_get_client_info()}
+* mysql_get_host_info:: @code{mysql_get_host_info()}
+* mysql_get_proto_info:: @code{mysql_get_proto_info()}
+* mysql_get_server_info:: @code{mysql_get_server_info()}
+* mysql_info:: @code{mysql_info()}
+* mysql_init:: @code{mysql_init()}
+* mysql_insert_id:: @code{mysql_insert_id()}
+* mysql_kill:: @code{mysql_kill()}
+* mysql_list_dbs:: @code{mysql_list_dbs()}
+* mysql_list_fields:: @code{mysql_list_fields()}
+* mysql_list_processes:: @code{mysql_list_processes()}
+* mysql_list_tables:: @code{mysql_list_tables()}
+* mysql_num_fields:: @code{mysql_num_fields()}
+* mysql_num_rows:: @code{mysql_num_rows()}
+* mysql_options:: @code{mysql_options()}
+* mysql_ping:: @code{mysql_ping()}
+* mysql_query:: @code{mysql_query()}
+* mysql_real_connect:: @code{mysql_real_connect()}
+* mysql_real_escape_string:: @code{mysql_real_escape_string()}
+* mysql_real_query:: @code{mysql_real_query()}
+* mysql_reload:: @code{mysql_reload()}
+* mysql_row_seek:: @code{mysql_row_seek()}
+* mysql_row_tell:: @code{mysql_row_tell()}
+* mysql_select_db:: @code{mysql_select_db()}
+* mysql_shutdown:: @code{mysql_shutdown()}
+* mysql_stat:: @code{mysql_stat()}
+* mysql_store_result:: @code{mysql_store_result()}
+* mysql_thread_id:: @code{mysql_thread_id()}
+* mysql_use_result:: @code{mysql_use_result()}
+* NULL mysql_store_result:: Why is it that after @code{mysql_query()} returns success, @code{mysql_store_result()} sometimes returns @code{NULL?}
+* Query results:: What results can I get from a query?
+* Getting unique ID:: How can I get the unique ID for the last inserted row?
+* C API linking problems:: Problems linking with the C API
+* Thread-safe clients:: How to make a thread-safe client
+@end menu
+
+In the descriptions below, a parameter or return value of @code{NULL} means
+@code{NULL} in the sense of the C programming language, not a
+@strong{MySQL} @code{NULL} value.
+
+Functions that return a value generally return a pointer or an integer.
+Unless specified otherwise, functions returning a pointer return a
+non-@code{NULL} value to indicate success or a @code{NULL} value to indicate
+an error, and functions returning an integer return zero to indicate success
+or non-zero to indicate an error. Note that ``non-zero'' means just that.
+Unless the function description says otherwise, do not test against a value
+other than zero:
+
+@example
+if (result) /* correct */
+ ... error ...
+
+if (result < 0) /* incorrect */
+ ... error ...
+
+if (result == -1) /* incorrect */
+ ... error ...
+@end example
+
+When a function returns an error, the @strong{Errors} subsection of the
+function description lists the possible types of errors. You can
+find out which of these occurred by calling @code{mysql_errno()}.
+A string representation of the error may be obtained by calling
+@code{mysql_error()}.
+
+@findex @code{mysql_affected_rows()}
+@node mysql_affected_rows, mysql_close, C API functions, C API functions
+@subsection @code{mysql_affected_rows()}
+
+@code{my_ulonglong mysql_affected_rows(MYSQL *mysql)}
+
+@subsubheading Description
+
+Returns the number of rows affected (changed) by the last @code{UPDATE},
+@code{DELETE} or @code{INSERT} query. May be called immediately after
+@code{mysql_query()} for @code{UPDATE}, @code{DELETE} or @code{INSERT}
+statements. For @code{SELECT} statements, @code{mysql_affected_rows()}
+works like @code{mysql_num_rows()}.
+
+@code{mysql_affected_rows()} is currently implemented as a macro.
+
+@subsubheading Return values
+
+An integer greater than zero indicates the number of rows affected or
+retrieved. Zero indicates that no records matched the @code{WHERE} clause in
+the query or that no query has yet been executed. -1 indicates that the
+query returned an error or that, for a @code{SELECT} query,
+@code{mysql_affected_rows()} was called prior to calling
+@code{mysql_store_result()}.
+
+@subsubheading Errors
+
+None.
+
+@subsubheading Example
+
+@example
+mysql_query(&mysql,"UPDATE products SET cost=cost*1.25 WHERE group=10");
+printf("%d products updated",mysql_affected_rows(&mysql));
+@end example
+
+@findex @code{mysql_close()}
+@node mysql_close, mysql_connect, mysql_affected_rows, C API functions
+@subsection @code{mysql_close()}
+
+@code{void mysql_close(MYSQL *mysql)}
+
+@subsubheading Description
+Closes a previously opened connection. @code{mysql_close()} also deallocates
+the connection handle pointed to by @code{mysql} if the handle was allocated
+automatically by @code{mysql_init()} or @code{mysql_connect()}.
+
+@subsubheading Return values
+
+None.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_connect()}
+@node mysql_connect, mysql_change_user, mysql_close, C API functions
+@subsection @code{mysql_connect()}
+
+@code{MYSQL *mysql_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd)}
+
+@subsubheading Description
+
+This function is deprecated. It is preferable to use
+@code{mysql_real_connect()} instead.
+
+@code{mysql_connect()} attempts to establish a connection to a @strong{MySQL}
+database engine running on @code{host}. @code{mysql_connect()} must complete
+successfully before you can execute any of the other API functions, with the
+exception of @code{mysql_get_client_info()}.
+
+The meanings of the parameters are the same as for the corresponding
+parameters for @code{mysql_real_connect()} with the difference that the
+connection parameter may be @code{NULL}. In this case the C API
+allocates memory for the connection structure automatically and frees it
+when you call @code{mysql_close()}. The disadvantage of this approach is
+that you can't retrieve an error message if the connection fails. (To
+get error information from @code{mysql_errno()} or @code{mysql_error()},
+you must provide a valid @code{MYSQL} pointer.)
+
+@subsubheading Return values
+
+Same as for @code{mysql_real_connect()}.
+
+@subsubheading Errors
+
+Same as for @code{mysql_real_connect()}.
+
+@findex @code{mysql_change_user()}
+@node mysql_change_user, mysql_character_set_name, mysql_connect, C API functions
+@subsection @code{mysql_change_user()}
+
+@code{my_bool mysql_change_user(MYSQL *mysql, const char *user, const
+char *password, const char *db)}
+
+@subsubheading Description
+
+Changes the user and causes the database specified by @code{db} to
+become the default (current) database on the connection specified by
+@code{mysql}. In subsequent queries, this database is the default for
+table references that do not include an explicit database specifier.
+
+This function was introduced in @strong{MySQL} 3.23.3.
+
+@code{mysql_change_user()} fails unless the connected user can be
+authenticated or if he doesn't have permission to use the database. In
+this case the user and database are not changed
+
+The @code{db} parameter may be set to @code{NULL} if you don't want to have a
+default database.
+
+@subsubheading Return values
+
+Zero for success. Non-zero if an error occurred.
+
+@subsubheading Errors
+
+The same that you can get from @code{mysql_real_connect()}.
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@item ER_UNKNOWN_COM_ERROR
+The @strong{MySQL} server doesn't implement this command (probably an old server)
+@item ER_ACCESS_DENIED_ERROR
+The user or password was wrong.
+@item ER_BAD_DB_ERROR
+The database didn't exists.
+@item ER_DBACCESS_DENIED_ERROR
+The user did not have access rights to the database.
+@item ER_WRONG_DB_NAME
+The database name was too long.
+@end table
+
+@subsubheading Example
+
+@example
+if (mysql_change_user(&mysql, "user", "password", "new_database"))
+@{
+ fprintf(stderr, "Failed to change user. Error: %s\n",
+ mysql_error(&mysql));
+@}
+@end example
+
+@findex @code{mysql_character_set_name()}
+@node mysql_character_set_name, mysql_create_db, mysql_change_user, C API functions
+@subsection @code{mysql_character_set_name()}
+
+@code{const char *mysql_character_set_name(MYSQL *mysql)}
+
+@subsubheading Description
+
+Returns the default character set for the current connection.
+
+@subsubheading Return values
+
+The default character set
+
+@subsubheading Errors
+None.
+
+
+@findex @code{mysql_create_db()}
+@node mysql_create_db, mysql_data_seek, mysql_character_set_name, C API functions
+@subsection @code{mysql_create_db()}
+
+@code{int mysql_create_db(MYSQL *mysql, const char *db)}
+
+@subsubheading Description
+Creates the database named by the @code{db} parameter.
+
+This function is deprecated. It is preferable to use @code{mysql_query()}
+to issue a SQL @code{CREATE DATABASE} statement instead.
+
+@subsubheading Return values
+
+Zero if the database was created successfully. Non-zero if an error
+occurred.
+
+@subsubheading Errors
+@table @code
+
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@subsubheading Example
+
+@example
+if(mysql_create_db(&mysql, "my_database"))
+@{
+ fprintf(stderr, "Failed to create new database. Error: %s\n",
+ mysql_error(&mysql));
+@}
+@end example
+
+@findex @code{mysql_data_seek()}
+@node mysql_data_seek, mysql_debug, mysql_create_db, C API functions
+@subsection @code{mysql_data_seek()}
+
+@code{void mysql_data_seek(MYSQL_RES *result, unsigned long long offset)}
+
+@subsubheading Description
+Seeks to an arbitrary row in a query result set. This requires that the
+result set structure contains the entire result of the query, so
+@code{mysql_data_seek()} may be used in conjunction only with
+@code{mysql_store_result()}, not with @code{mysql_use_result()}.
+
+The offset should be a value in the range from 0 to
+@code{mysql_num_rows(result)-1}.
+
+@subsubheading Return values
+
+None.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_debug()}
+@node mysql_debug, mysql_drop_db, mysql_data_seek, C API functions
+@subsection @code{mysql_debug()}
+
+@code{void mysql_debug(char *debug)}
+
+@subsubheading Description
+Does a @code{DBUG_PUSH} with the given string. @code{mysql_debug()} uses the
+Fred Fish debug library. To use this function, you must compile the client
+library to support debugging.
+@xref{Debugging server}. @xref{Debugging client}.
+
+@subsubheading Return values
+
+None.
+
+@subsubheading Errors
+None.
+
+@subsubheading Example
+
+The call shown below causes the client library to generate a trace file in
+@file{/tmp/client.trace} on the client machine:
+
+@example
+mysql_debug("d:t:O,/tmp/client.trace");
+@end example
+
+@findex @code{mysql_drop_db()}
+@node mysql_drop_db, mysql_dump_debug_info, mysql_debug, C API functions
+@subsection @code{mysql_drop_db()}
+
+@code{int mysql_drop_db(MYSQL *mysql, const char *db)}
+
+@subsubheading Description
+Drops the database named by the @code{db} parameter.
+
+This function is deprecated. It is preferable to use @code{mysql_query()}
+to issue a SQL @code{DROP DATABASE} statement instead.
+
+@subsubheading Return values
+
+Zero if the database was dropped successfully. Non-zero if an error
+occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@subsubheading Example
+
+@example
+if(mysql_drop_db(&mysql, "my_database"))
+ fprintf(stderr, "Failed to drop the database: Error: %s\n",
+ mysql_error(&mysql));
+@end example
+
+@findex @code{mysql_dump_debug_info()}
+@node mysql_dump_debug_info, mysql_eof, mysql_drop_db, C API functions
+@subsection @code{mysql_dump_debug_info()}
+
+@code{int mysql_dump_debug_info(MYSQL *mysql)}
+
+@subsubheading Description
+
+Instructs the server to write some debug information to the log. The
+connected user must have the @strong{process} privilege for this to work.
+
+@subsubheading Return values
+
+Zero if the command was successful. Non-zero if an error occurred.
+
+@subsubheading Errors
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_eof()}
+@node mysql_eof, mysql_errno, mysql_dump_debug_info, C API functions
+@subsection @code{mysql_eof()}
+
+@code{my_bool mysql_eof(MYSQL_RES *result)}
+
+@subsubheading Description
+
+This function is deprecated. @code{mysql_errno()} or @code{mysql_error()}
+may be used instead.
+
+@code{mysql_eof()} determines whether or not the last row of a result
+set has been read.
+
+If you acquire a result set from a successful call to
+@code{mysql_store_result()}, the client receives the entire set in one
+operation. In this case, a @code{NULL} return from @code{mysql_fetch_row()}
+always means the end of the result set has been reached and it is
+unnecessary to call @code{mysql_eof()}.
+
+On the other hand, if you use @code{mysql_use_result()} to initiate a result
+set retrieval, the rows of the set are obtained from the server one by one as
+you call @code{mysql_fetch_row()} repeatedly. Because an error may occur on
+the connection during this process, a @code{NULL} return value from
+@code{mysql_fetch_row()} does not necessarily mean the end of the result set
+was reached normally. In this case, you can use @code{mysql_eof()} to
+determine what happened. @code{mysql_eof()} returns a non-zero value if the
+end of the result set was reached and zero if an error occurred.
+
+Historically, @code{mysql_eof()} predates the standard @strong{MySQL} error
+functions @code{mysql_errno()} and @code{mysql_error()}. Because those error
+functions provide the same information, their use is preferred over
+@code{mysql_eof()}, which is now deprecated. (In fact, they provide more
+information, because @code{mysql_eof()} returns only a boolean value whereas
+the error functions indicate a reason for the error when one occurs.)
+
+@subsubheading Return values
+
+Zero if no error occurred. Non-zero if the end of the result set has been
+reached.
+
+@subsubheading Errors
+None.
+
+@subsubheading Example
+
+The following example shows how you might use @code{mysql_eof()}:
+
+@example
+mysql_query(&mysql,"SELECT * FROM some_table");
+result = mysql_use_result(&mysql);
+while((row = mysql_fetch_row(result)))
+@{
+ // do something with data
+@}
+if(!mysql_eof(result)) // mysql_fetch_row() failed due to an error
+@{
+ fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
+@}
+@end example
+
+However, you can achieve the same effect with the standard @strong{MySQL}
+error functions:
+
+@example
+mysql_query(&mysql,"SELECT * FROM some_table");
+result = mysql_use_result(&mysql);
+while((row = mysql_fetch_row(result)))
+@{
+ // do something with data
+@}
+if(mysql_errno(&mysql)) // mysql_fetch_row() failed due to an error
+@{
+ fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
+@}
+@end example
+
+@findex @code{mysql_errno()}
+@node mysql_errno, mysql_error, mysql_eof, C API functions
+@subsection @code{mysql_errno()}
+
+@code{unsigned int mysql_errno(MYSQL *mysql)}
+
+@subsubheading Description
+
+For the connection specified by @code{mysql}, @code{mysql_errno()} returns
+the error code for the most recently invoked API function that can succeed
+or fail. A return value of zero means that no error occurred. Client error
+message numbers are listed in the @strong{MySQL} @file{errmsg.h} header file.
+Server error message numbers are listed in @file{mysqld_error.h}
+
+@subsubheading Return values:
+
+An error code value. Zero if no error occurred.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_error()}
+@node mysql_error, mysql_escape_string, mysql_errno, C API functions
+@subsection @code{mysql_error()}
+
+@code{char *mysql_error(MYSQL *mysql)}
+
+@subsubheading Description
+
+For the connection specified by @code{mysql}, @code{mysql_error()} returns
+the error message for the most recently invoked API function that can succeed
+or fail. An empty string (@code{""}) is returned if no error occurred.
+This means the following two tests are equivalent:
+
+@example
+if(mysql_errno(&mysql))
+@{
+ // an error occurred
+@}
+
+if(mysql_error(&mysql)[0] != '\0')
+@{
+ // an error occurred
+@}
+@end example
+
+The language of the client error messages may be changed by
+recompiling the @strong{MySQL} client library. Currently you can choose
+error messages in several different languages.
+@xref{Languages}.
+
+@subsubheading Return values
+
+A character string that describes the error. An empty string if no error
+occurred.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_escape_string()}
+@node mysql_escape_string, mysql_fetch_field, mysql_error, C API functions
+@subsection @code{mysql_escape_string()}
+
+You should use @code{mysql_real_escape_string()} instead!
+
+This is identical to @code{mysql_real_escape_string()} except that it takes
+the connection as the first argument. @code{mysql_real_escape_string()}
+will escape the string according to the current character set while @code{mysql_escape_string()}
+does not respect the current charset setting.
+
+@findex @code{mysql_fetch_field()}
+@node mysql_fetch_field, mysql_fetch_fields, mysql_escape_string, C API functions
+@subsection @code{mysql_fetch_field()}
+
+@code{MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)}
+
+@subsubheading Description
+
+Returns the definition of one column of a result set as a @code{MYSQL_FIELD}
+structure. Call this function repeatedly to retrieve information about all
+columns in the result set. @code{mysql_fetch_field()} returns @code{NULL}
+when no more fields are left.
+
+@code{mysql_fetch_field()} is reset to return information about the first
+field each time you execute a new @code{SELECT} query. The field returned by
+@code{mysql_fetch_field()} is also affected by calls to
+@code{mysql_field_seek()}.
+
+If you've called @code{mysql_query()} to perform a @code{SELECT} on a table
+but have not called @code{mysql_store_result()}, @strong{MySQL} returns the
+default blob length (8K bytes) if you call @code{mysql_fetch_field()} to ask
+for the length of a @code{BLOB} field. (The 8K size is chosen because
+@strong{MySQL} doesn't know the maximum length for the @code{BLOB}. This
+should be made configurable sometime.) Once you've retrieved the result set,
+@code{field->max_length} contains the length of the largest value for this
+column in the specific query.
+
+@subsubheading Return values
+
+The @code{MYSQL_FIELD} structure for the current column. @code{NULL}
+if no columns are left.
+
+@subsubheading Errors
+None.
+
+@subsubheading Example
+
+@example
+MYSQL_FIELD *field;
+
+while((field = mysql_fetch_field(result)))
+@{
+ printf("field name %s\n", field->name);
+@}
+@end example
+
+@findex @code{mysql_fetch_fields()}
+@node mysql_fetch_fields, mysql_fetch_field_direct, mysql_fetch_field, C API functions
+@subsection @code{mysql_fetch_fields()}
+
+@code{MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)}
+
+@subsubheading Description
+
+Returns an array of all @code{MYSQL_FIELD} structures for a result set.
+Each structure provides the field definition for one column of the result
+set.
+
+@subsubheading Return values
+
+An array of @code{MYSQL_FIELD} structures for all columns of a result set.
+
+@subsubheading Errors
+None.
+
+@subsubheading Example
+
+@example
+unsigned int num_fields;
+unsigned int i;
+MYSQL_FIELD *fields;
+
+num_fields = mysql_num_fields(result);
+fields = mysql_fetch_fields(result);
+for(i = 0; i < num_fields; i++)
+@{
+ printf("Field %u is %s\n", i, fields[i].name);
+@}
+@end example
+
+@findex @code{mysql_fetch_field_direct()}
+@node mysql_fetch_field_direct, mysql_fetch_lengths, mysql_fetch_fields, C API functions
+@subsection @code{mysql_fetch_field_direct()}
+
+@code{MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES *result, unsigned int fieldnr)}
+
+@subsubheading Description
+
+Given a field number @code{fieldnr} for a column within a result set, returns
+that column's field definition as a @code{MYSQL_FIELD} structure. You may use
+this function to retrieve the definition for an arbitrary column. The value
+of @code{fieldnr} should be in the range from 0 to
+@code{mysql_num_fields(result)-1}.
+
+@subsubheading Return values
+
+The @code{MYSQL_FIELD} structure for the specified column.
+
+@subsubheading Errors
+None.
+
+@subsubheading Example
+
+@example
+unsigned int num_fields;
+unsigned int i;
+MYSQL_FIELD *field;
+
+num_fields = mysql_num_fields(result);
+for(i = 0; i < num_fields; i++)
+@{
+ field = mysql_fetch_field_direct(result, i);
+ printf("Field %u is %s\n", i, field->name);
+@}
+@end example
+
+@findex @code{mysql_fetch_lengths()}
+@node mysql_fetch_lengths, mysql_fetch_row, mysql_fetch_field_direct, C API functions
+@subsection @code{mysql_fetch_lengths()}
+
+@code{unsigned long *mysql_fetch_lengths(MYSQL_RES *result)}
+
+@subsubheading Description
+
+Returns the lengths of the columns of the current row within a result set.
+If you plan to copy field values, this length information is also useful for
+optimization, because you can avoid calling @code{strlen()}. In addition, if
+the result set contains binary data, you @emph{must} use this function to
+determine the size of the data, because @code{strlen()} returns incorrect
+results for any field containing null characters.
+
+The length for empty columns and for columns containing @code{NULL} values is
+zero. To see how to distinguish these two cases, see the description for
+@code{mysql_fetch_row()}.
+
+@subsubheading Return values
+
+An array of unsigned long integers representing the size of each column (not
+including any terminating null characters).
+@code{NULL} if an error occurred.
+
+@subsubheading Errors
+@code{mysql_fetch_lengths()} is valid only for the current row of the result
+set. It returns @code{NULL} if you call it before calling
+@code{mysql_fetch_row()} or after retrieving all rows in the result.
+
+@subsubheading Example
+
+@example
+MYSQL_ROW row;
+unsigned long *lengths;
+unsigned int num_fields;
+unsigned int i;
+
+row = mysql_fetch_row(result);
+if (row)
+@{
+ num_fields = mysql_num_fields(result);
+ lengths = mysql_fetch_lengths(result);
+ for(i = 0; i < num_fields; i++)
+ @{
+ printf("Column %u is %lu bytes in length.\n", i, lengths[i]);
+ @}
+@}
+@end example
+
+@findex @code{mysql_fetch_row()}
+@node mysql_fetch_row, mysql_field_count, mysql_fetch_lengths, C API functions
+@subsection @code{mysql_fetch_row()}
+
+@code{MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)}
+
+@subsubheading Description
+
+Retrieves the next row of a result set. When used after
+@code{mysql_store_result()}, @code{mysql_fetch_row()} returns @code{NULL}
+when there are no more rows to retrieve. When used after
+@code{mysql_use_result()}, @code{mysql_fetch_row()} returns @code{NULL} when
+there are no more rows to retrieve or if an error occurred.
+
+The number of values in the row is given by @code{mysql_num_fields(result)}.
+If @code{row} holds the return value from a call to @code{mysql_fetch_row()},
+pointers to the values are accessed as @code{row[0]} to
+@code{row[mysql_num_fields(result)-1]}. @code{NULL} values in the row are
+indicated by @code{NULL} pointers.
+
+The lengths of the field values in the row may be obtained by calling
+@code{mysql_fetch_lengths()}. Empty fields and fields containing
+@code{NULL} both have length 0; you can distinguish these by checking
+the pointer for the field value. If the pointer is @code{NULL}, the field
+is @code{NULL}; otherwise the field is empty.
+
+@subsubheading Return values
+
+A @code{MYSQL_ROW} structure for the next row. @code{NULL} if
+there are no more rows to retrieve or if an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@subsubheading Example
+
+@example
+MYSQL_ROW row;
+unsigned int num_fields;
+unsigned int i;
+
+num_fields = mysql_num_fields(result);
+while ((row = mysql_fetch_row(result)))
+@{
+ unsigned long *lengths;
+ lengths = mysql_fetch_lengths(result);
+ for(i = 0; i < num_fields; i++)
+ @{
+ printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL");
+ @}
+ printf("\n");
+@}
+@end example
+
+@findex @code{mysql_field_count()}
+@node mysql_field_count, mysql_field_seek, mysql_fetch_row, C API functions
+@subsection @code{mysql_field_count()}
+
+@code{unsigned int mysql_field_count(MYSQL *mysql)}
+
+If you are using a version of @strong{MySQL} earlier than 3.22.24, you
+should use @code{unsigned int mysql_num_fields(MYSQL *mysql)} instead.
+
+@subsubheading Description
+
+Returns the number of columns for the most recent query on the connection.
+
+The normal use of this function is when @code{mysql_store_result()}
+returned @code{NULL} (and thus you have no result set pointer).
+In this case, you can call @code{mysql_field_count()} to
+determine whether or not @code{mysql_store_result()} should have produced a
+non-empty result. This allows the client program to take proper action
+without knowing whether or not the query was a @code{SELECT} (or
+@code{SELECT}-like) statement. The example shown below illustrates how this
+may be done.
+
+@xref{NULL mysql_store_result, , @code{NULL mysql_store_result()}}.
+
+@subsubheading Return values
+
+An unsigned integer representing the number of fields in a result set.
+
+@subsubheading Errors
+None.
+
+@subsubheading Example
+
+@example
+MYSQL_RES *result;
+unsigned int num_fields;
+unsigned int num_rows;
+
+if (mysql_query(&mysql,query_string))
+@{
+ // error
+@}
+else // query succeeded, process any data returned by it
+@{
+ result = mysql_store_result(&mysql);
+ if (result) // there are rows
+ @{
+ num_fields = mysql_num_fields(result);
+ // retrieve rows, then call mysql_free_result(result)
+ @}
+ else // mysql_store_result() returned nothing; should it have?
+ @{
+ if(mysql_field_count(&mysql) == 0)
+ @{
+ // query does not return data
+ // (it was not a SELECT)
+ num_rows = mysql_affected_rows(&mysql);
+ @}
+ else // mysql_store_result() should have returned data
+ @{
+ fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
+ @}
+ @}
+@}
+@end example
+
+An alternative is to replace the @code{mysql_field_count(&mysql)} call with
+@code{mysql_errno(&mysql)}. In this case, you are checking directly for an
+error from @code{mysql_store_result()} rather than inferring from the value
+of @code{mysql_field_count()} whether or not the statement was a
+@code{SELECT}.
+
+@findex @code{mysql_field_seek()}
+@node mysql_field_seek, mysql_field_tell, mysql_field_count, C API functions
+@subsection @code{mysql_field_seek()}
+
+@code{MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset)}
+
+@subsubheading Description
+
+Sets the field cursor to the given offset. The next call to
+@code{mysql_fetch_field()} will retrieve the field definition of the column
+associated with that offset.
+
+To seek to the beginning of a row, pass an @code{offset} value of zero.
+
+@subsubheading Return values
+
+The previous value of the field cursor.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_field_tell()}
+@node mysql_field_tell, mysql_free_result, mysql_field_seek, C API functions
+@subsection @code{mysql_field_tell()}
+
+@code{MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES *result)}
+
+@subsubheading Description
+
+Returns the position of the field cursor used for the last
+@code{mysql_fetch_field()}. This value can be used as an argument to
+@code{mysql_field_seek()}.
+
+@subsubheading Return values
+
+The current offset of the field cursor.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_free_result()}
+@node mysql_free_result, mysql_get_client_info, mysql_field_tell, C API functions
+@subsection @code{mysql_free_result()}
+
+@code{void mysql_free_result(MYSQL_RES *result)}
+
+@subsubheading Description
+
+Frees the memory allocated for a result set by @code{mysql_store_result()},
+@code{mysql_use_result()}, @code{mysql_list_dbs()}, etc. When you are done
+with a result set, you must free the memory it uses by calling
+@code{mysql_free_result()}.
+
+@subsubheading Return values
+
+None.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_get_client_info()}
+@node mysql_get_client_info, mysql_get_host_info, mysql_free_result, C API functions
+@subsection @code{mysql_get_client_info()}
+
+@code{char *mysql_get_client_info(void)}
+
+@subsubheading Description
+
+Returns a string that represents the client library version.
+
+@subsubheading Return values
+
+A character string that represents the @strong{MySQL} client library version.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_get_host_info()}
+@node mysql_get_host_info, mysql_get_proto_info, mysql_get_client_info, C API functions
+@subsection @code{mysql_get_host_info()}
+
+@code{char *mysql_get_host_info(MYSQL *mysql)}
+
+@subsubheading Description
+
+Returns a string describing the type of connection in use, including the
+server host name.
+
+@subsubheading Return values
+
+A character string representing the server host name and the connection type.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_get_proto_info()}
+@node mysql_get_proto_info, mysql_get_server_info, mysql_get_host_info, C API functions
+@subsection @code{mysql_get_proto_info()}
+
+@code{unsigned int mysql_get_proto_info(MYSQL *mysql)}
+
+@subsubheading Description
+
+Returns the protocol version used by current connection.
+
+@subsubheading Return values
+
+An unsigned integer representing the protocol version used by the current
+connection.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_get_server_info()}
+@node mysql_get_server_info, mysql_info, mysql_get_proto_info, C API functions
+@subsection @code{mysql_get_server_info()}
+
+@code{char *mysql_get_server_info(MYSQL *mysql)}
+
+@subsubheading Description
+
+Returns a string that represents the server version number.
+
+@subsubheading Return values
+
+A character string that represents the server version number.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_info()}
+@node mysql_info, mysql_init, mysql_get_server_info, C API functions
+@subsection @code{mysql_info()}
+
+@code{char *mysql_info(MYSQL *mysql)}
+
+@subsubheading Description
+
+Retrieves a string providing information about the most recently executed
+query, but only for the statements listed below. For other statements,
+@code{mysql_info()} returns @code{NULL}. The format of the string varies
+depending on the type of query, as described below. The numbers are
+illustrative only; the string will contain values appropriate for the query.
+
+@table @code
+@item INSERT INTO ... SELECT ...
+String format: @code{Records: 100 Duplicates: 0 Warnings: 0}
+@item INSERT INTO ... VALUES (...),(...),(...)...
+String format: @code{Records: 3 Duplicates: 0 Warnings: 0}
+@item LOAD DATA INFILE ...
+String format: @code{Records: 1 Deleted: 0 Skipped: 0 Warnings: 0}
+@item ALTER TABLE
+String format: @code{Records: 3 Duplicates: 0 Warnings: 0}
+@item UPDATE
+String format: @code{Rows matched: 40 Changed: 40 Warnings: 0}
+@end table
+
+Note that @code{mysql_info()} returns a non-@code{NULL} value for the
+@code{INSERT ... VALUES} statement only if multiple value lists are
+specified in the statement.
+
+@subsubheading Return values
+
+A character string representing additional information about the most
+recently executed query. @code{NULL} if no information is available for the
+query.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_init()}
+@node mysql_init, mysql_insert_id, mysql_info, C API functions
+@subsection @code{mysql_init()}
+
+@code{MYSQL *mysql_init(MYSQL *mysql)}
+
+@subsubheading Description
+
+Allocates or initializes a @code{MYSQL} object suitable for
+@code{mysql_real_connect()}. If @code{mysql} is a @code{NULL} pointer, the
+function allocates, initializes and returns a new object. Otherwise the
+object is initialized and the address of the object is returned. If
+@code{mysql_init()} allocates a new object, it will be freed when
+@code{mysql_close()} is called to close the connection.
+
+@subsubheading Return values
+
+An initialized @code{MYSQL*} handle. @code{NULL} if there was
+insufficient memory to allocate a new object.
+
+@subsubheading Errors
+In case of insufficient memory, @code{NULL} is returned.
+
+@findex @code{mysql_insert_id()}
+@node mysql_insert_id, mysql_kill, mysql_init, C API functions
+@subsection @code{mysql_insert_id()}
+
+@code{my_ulonglong mysql_insert_id(MYSQL *mysql)}
+
+@subsubheading Description
+
+Returns the ID generated for an @code{AUTO_INCREMENT} column by the previous
+query. Use this function after you have performed an @code{INSERT} query
+into a table that contains an @code{AUTO_INCREMENT} field.
+
+Note that @code{mysql_insert_id()} returns @code{0} if the previous query
+does not generate an @code{AUTO_INCREMENT} value. If you need to save
+the value for later, be sure to call @code{mysql_insert_id()} immediately
+after the query that generates the value.
+
+Also note that the value of the SQL @code{LAST_INSERT_ID()} function always
+contains the most recently generated @code{AUTO_INCREMENT} value, and is
+not reset between queries because the value of that function is maintained
+in the server.
+
+@subsubheading Return values
+
+The value of the @code{AUTO_INCREMENT} field that was updated by the previous
+query. Returns zero if there was no previous query on the connection or if
+the query did not update an @code{AUTO_INCREMENT} value.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_kill()}
+@node mysql_kill, mysql_list_dbs, mysql_insert_id, C API functions
+@subsection @code{mysql_kill()}
+
+@code{int mysql_kill(MYSQL *mysql, unsigned long pid)}
+
+@subsubheading Description
+
+Asks the server to kill the thread specified by @code{pid}.
+
+@subsubheading Return values
+
+Zero for success. Non-zero if an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_list_dbs()}
+@node mysql_list_dbs, mysql_list_fields, mysql_kill, C API functions
+@subsection @code{mysql_list_dbs()}
+
+@code{MYSQL_RES *mysql_list_dbs(MYSQL *mysql, const char *wild)}
+
+@subsubheading Description
+
+Returns a result set consisting of database names on the server that match
+the simple regular expression specified by the @code{wild} parameter.
+@code{wild} may contain the wildcard characters @samp{%} or @samp{_}, or may
+be a @code{NULL} pointer to match all databases. Calling
+@code{mysql_list_dbs()} is similar to executing the query @code{SHOW
+databases [LIKE wild]}.
+
+You must free the result set with @code{mysql_free_result()}.
+
+@subsubheading Return values
+
+A @code{MYSQL_RES} result set for success. @code{NULL} if an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_OUT_OF_MEMORY
+Out of memory.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_list_fields()}
+@node mysql_list_fields, mysql_list_processes, mysql_list_dbs, C API functions
+@subsection @code{mysql_list_fields()}
+
+@code{MYSQL_RES *mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)}
+
+@subsubheading Description
+
+Returns a result set consisting of field names in the given table that match
+the simple regular expression specified by the @code{wild} parameter.
+@code{wild} may contain the wildcard characters @samp{%} or @samp{_}, or may
+be a @code{NULL} pointer to match all fields. Calling
+@code{mysql_list_fields()} is similar to executing the query @code{SHOW
+COLUMNS FROM tbl_name [LIKE wild]}.
+
+Note that it's recommended that you use @code{SHOW COLUMNS FROM tbl_name}
+instead of @code{mysql_list_fields()}.
+
+You must free the result set with @code{mysql_free_result()}.
+
+@subsubheading Return values
+
+A @code{MYSQL_RES} result set for success. @code{NULL} if an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_list_processes()}
+@node mysql_list_processes, mysql_list_tables, mysql_list_fields, C API functions
+@subsection @code{mysql_list_processes()}
+
+@code{MYSQL_RES *mysql_list_processes(MYSQL *mysql)}
+
+@subsubheading Description
+
+Returns a result set describing the current server threads. This is the same
+kind of information as that reported by @code{mysqladmin processlist} or
+a @code{SHOW PROCESSLIST} query.
+
+You must free the result set with @code{mysql_free_result()}.
+
+@subsubheading Return values
+
+A @code{MYSQL_RES} result set for success. @code{NULL} if an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_list_tables()}
+@node mysql_list_tables, mysql_num_fields, mysql_list_processes, C API functions
+@subsection @code{mysql_list_tables()}
+
+@code{MYSQL_RES *mysql_list_tables(MYSQL *mysql, const char *wild)}
+
+@subsubheading Description
+
+Returns a result set consisting of table names in the current database that
+match the simple regular expression specified by the @code{wild} parameter.
+@code{wild} may contain the wildcard characters @samp{%} or @samp{_}, or may
+be a @code{NULL} pointer to match all tables. Calling
+@code{mysql_list_tables()} is similar to executing the query @code{SHOW
+tables [LIKE wild]}.
+
+You must free the result set with @code{mysql_free_result()}.
+
+@subsubheading Return values
+
+A @code{MYSQL_RES} result set for success. @code{NULL} if an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_num_fields()}
+@findex @code{mysql_field_count()}
+@node mysql_num_fields, mysql_num_rows, mysql_list_tables, C API functions
+@subsection @code{mysql_num_fields()}
+
+@code{unsigned int mysql_num_fields(MYSQL_RES *result)}
+
+or
+
+@code{unsigned int mysql_num_fields(MYSQL *mysql)}
+
+The second form doesn't work on @strong{MySQL} 3.22.24 or newer. To pass a
+@code{MYSQL*} argument, you must use
+@code{unsigned int mysql_field_count(MYSQL *mysql)} instead.
+
+@subsubheading Description
+
+Returns the number of columns in a result set.
+
+Note that you can get the number of columns either from a pointer to a result
+set or to a connection handle. You would use the connection handle if
+@code{mysql_store_result()} or @code{mysql_use_result()} returned
+@code{NULL} (and thus you have no result set pointer). In this case, you can
+call @code{mysql_field_count()} to determine whether or not
+@code{mysql_store_result()} should have produced a non-empty result. This
+allows the client program to take proper action without knowing whether or
+not the query was a @code{SELECT} (or @code{SELECT}-like) statement. The
+example shown below illustrates how this may be done.
+
+@xref{NULL mysql_store_result, , @code{NULL mysql_store_result()}}.
+
+@subsubheading Return values
+
+An unsigned integer representing the number of fields in a result set.
+
+@subsubheading Errors
+None.
+
+@subsubheading Example
+
+@example
+MYSQL_RES *result;
+unsigned int num_fields;
+unsigned int num_rows;
+
+if (mysql_query(&mysql,query_string))
+@{
+ // error
+@}
+else // query succeeded, process any data returned by it
+@{
+ result = mysql_store_result(&mysql);
+ if (result) // there are rows
+ @{
+ num_fields = mysql_num_fields(result);
+ // retrieve rows, then call mysql_free_result(result)
+ @}
+ else // mysql_store_result() returned nothing; should it have?
+ @{
+ if (mysql_errno(&mysql))
+ @{
+ fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
+ @}
+ else if (mysql_field_count(&mysql) == 0)
+ @{
+ // query does not return data
+ // (it was not a SELECT)
+ num_rows = mysql_affected_rows(&mysql);
+ @}
+ @}
+@}
+@end example
+
+An alternative (if you KNOW that your query should have returned a result set)
+is to replace the @code{mysql_errno(&mysql)} call with a check if
+@code{mysql_field_count(&mysql)} is = 0. This will only happen if something
+went wrong.
+
+@findex @code{mysql_num_rows()}
+@node mysql_num_rows, mysql_options, mysql_num_fields, C API functions
+@subsection @code{mysql_num_rows()}
+
+@code{my_ulonglong mysql_num_rows(MYSQL_RES *result)}
+
+@subsubheading Description
+
+Returns the number of rows in the result set.
+
+The use of @code{mysql_num_rows()} depends on whether you use
+@code{mysql_store_result()} or @code{mysql_use_result()} to return the result
+set. If you use @code{mysql_store_result()}, @code{mysql_num_rows()} may be
+called immediately. If you use @code{mysql_use_result()},
+@code{mysql_num_rows()} will not return the correct value until all the rows
+in the result set have been retrieved.
+
+@subsubheading Return values
+
+The number of rows in the result set.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_options()}
+@node mysql_options, mysql_ping, mysql_num_rows, C API functions
+@subsection @code{mysql_options()}
+
+@code{int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg)}
+
+@subsubheading Description
+
+Can be used to set extra connect options and affect behavior for a connection.
+This function may be called multiple times to set several options.
+
+@code{mysql_options()} should be called after @code{mysql_init()} and before
+@code{mysql_connect()} or @code{mysql_real_connect()}.
+
+The @code{option} argument is the option that you want to set; the @code{arg}
+argument is the value for the option. If the option is an integer, then
+@code{arg} should point to the value of the integer.
+
+Possible options values:
+
+@multitable @columnfractions .25 .25 .5
+@item @strong{Option} @tab @strong{Argument type} @tab @strong{Function}
+@item @code{MYSQL_OPT_CONNECT_TIMEOUT} @tab @code{unsigned int *} @tab Connect timeout in seconds.
+@item @code{MYSQL_OPT_COMPRESS} @tab Not used @tab Use the compressed client/server protocol.
+@item @code{MYSQL_OPT_NAMED_PIPE} @tab Not used @tab Use named pipes to connect to a @strong{MySQL} server on NT.
+@item @code{MYSQL_INIT_COMMAND} @tab @code{char *} @tab Command to execute when connecting to the @strong{MySQL} server. Will automatically be re-executed when reconnecting.
+@item @code{MYSQL_READ_DEFAULT_FILE} @tab @code{char *} @tab Read options from the named option file instead of from @file{my.cnf}.
+@item @code{MYSQL_READ_DEFAULT_GROUP} @tab @code{char *} @tab Read options from the named group from @file{my.cnf} or the file specified with @code{MYSQL_READ_DEFAULT_FILE}.
+@end multitable
+
+Note that the group @code{client} is always read if you use
+@code{MYSQL_READ_DEFAULT_FILE} or @code{MYSQL_READ_DEFAULT_GROUP}.
+
+The specified group in the option file may contain the following options:
+
+@multitable @columnfractions .3 .7
+@item @code{compress} @tab Use the compressed client/server protocol.
+@item @code{database} @tab Connect to this database if no database was specified in the connect command.
+@item @code{debug} @tab Debug options.
+@item @code{host} @tab Default host name.
+@item @code{init-command} @tab Command to execute when connecting to @strong{MySQL} server. Will automatically be re-executed when reconnecting.
+@item @code{password} @tab Default password.
+@item @code{pipe} @tab Use named pipes to connect to a @strong{MySQL} server on NT.
+@item @code{port} @tab Default port number.
+@item @code{return-found-rows} @tab Tell @code{mysql_info()} to return found rows instead of updated rows when using @code{UPDATE}.
+@item @code{socket} @tab Default socket number.
+@item @code{timeout} @tab Connect timeout in seconds.
+@item @code{user} @tab Default user.
+@end multitable
+
+For more information about option files, see @ref{Option files}.
+
+@subsubheading Return values
+
+Zero for success. Non-zero if you used an unknown option.
+
+@subsubheading Example
+
+@example
+MYSQL mysql;
+
+mysql_init(&mysql);
+mysql_options(&mysql,MYSQL_OPT_COMPRESS,0);
+mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"odbc");
+if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0))
+@{
+ fprintf(stderr, "Failed to connect to database: Error: %s\n",
+ mysql_error(&mysql));
+@}
+@end example
+
+The above requests the client to use the compressed client/server protocol and
+read the additional options from the @code{odbc} section in the @code{my.cnf}
+file.
+
+@findex @code{mysql_ping()}
+@node mysql_ping, mysql_query, mysql_options, C API functions
+@subsection @code{mysql_ping()}
+
+@code{int mysql_ping(MYSQL *mysql)}
+
+@subsubheading Description
+
+Checks whether or not the connection to the server is working. If it has gone
+down, an automatic reconnection is attempted.
+
+This function can be used by clients that remain idle for a long while,
+to check whether or not the server has closed the connection and reconnect
+if necessary.
+
+@subsubheading Return values
+
+Zero if the server is alive. Non-zero if an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_query()}
+@node mysql_query, mysql_real_connect, mysql_ping, C API functions
+@subsection @code{mysql_query()}
+
+@code{int mysql_query(MYSQL *mysql, const char *query)}
+
+@subsubheading Description
+Executes the SQL query pointed to by the null-terminated string @code{query}.
+The query must consist of a single SQL statement. You should not add
+a terminating semicolon (@samp{;}) or @code{\g} to the statement.
+
+@code{mysql_query()} cannot be used for queries that contain binary data; you
+should use @code{mysql_real_query()} instead. (Binary data may contain the
+@samp{\0} character, which @code{mysql_query()} interprets as the end of the
+query string.)
+
+If you want to know if the query should return a result set or not, you can
+use @code{mysql_field_count()} to check for this.
+@xref{mysql_field_count, @code{mysql_field_count}}.
+
+@subsubheading Return values
+
+Zero if the query was successful. Non-zero if an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_real_connect()}
+@node mysql_real_connect, mysql_real_escape_string, mysql_query, C API functions
+@subsection @code{mysql_real_connect()}
+
+@code{MYSQL *mysql_real_connect(MYSQL *mysql, const char *host,
+ const char *user, const char *passwd, const char *db,
+ unsigned int port, const char *unix_socket,
+ unsigned int client_flag)}
+
+@subsubheading Description
+
+@code{mysql_real_connect()} attempts to establish a connection to a
+@strong{MySQL} database engine running on @code{host}.
+@code{mysql_real_connect()} must complete successfully before you can execute
+any of the other API functions, with the exception of
+@code{mysql_get_client_info()}.
+
+The parameters are specified as follows:
+
+@itemize @bullet
+@item
+The first parameter should be the address of an existing @code{MYSQL}
+structure. Before calling @code{mysql_real_connect()} you must call
+@code{mysql_init()} to initialize the @code{MYSQL} structure. See the
+example below.
+
+@item
+The value of @code{host} may be either a hostname or an IP address. If
+@code{host} is @code{NULL} or the string @code{"localhost"}, a connection to
+the local host is assumed. If the OS supports sockets (Unix) or named pipes
+(Win32), they are used instead of TCP/IP to connect to the server.
+
+@item
+The @code{user} parameter contains the user's @strong{MySQL} login ID. If
+@code{user} is @code{NULL}, the current user is assumed. Under Unix, this is
+the current login name. Under Windows ODBC, the current user name must be
+specified explicitly.
+@xref{ODBC administrator}.
+
+@item
+The @code{passwd} parameter contains the password for @code{user}. If
+@code{passwd} is @code{NULL}, only entries in the @code{user} table for the
+user that have a blank password field will be checked for a match. This
+allows the database administrator to set up the @strong{MySQL} privilege
+system in such a way that users get different privileges depending on whether
+or not they have specified a password.
+
+Note: Do not attempt to encrypt the password before calling
+@code{mysql_real_connect()}; password encryption is handled automatically by
+the client API.
+
+@item
+@code{db} is the database name.
+If @code{db} is not @code{NULL}, the connection will set the default
+database to this value.
+
+@item
+If @code{port} is not 0, the value will be used as the port number
+for the TCP/IP connection. Note that the @code{host} parameter
+determines the type of the connection.
+
+@item
+If @code{unix_socket} is not @code{NULL}, the string specifies the
+socket or named pipe that should be used. Note that the @code{host}
+parameter determines the type of the connection.
+
+@item
+The value of @code{client_flag} is usually 0, but can be set to a combination
+of the following flags in very special circumstances:
+
+@multitable @columnfractions .25 .7
+@item @strong{Flag name} @tab @strong{Flag meaning}
+@item @code{CLIENT_FOUND_ROWS} @tab Return the number of found (matched) rows, not the number of affected rows.
+@item @code{CLIENT_NO_SCHEMA} @tab Don't allow the @code{db_name.tbl_name.col_name} syntax. This is for ODBC; It causes the parser to generate an error if you use that syntax, which is useful for trapping bugs in some ODBC programs.
+@item @code{CLIENT_COMPRESS} @tab Use compression protocol.
+@item @code{CLIENT_ODBC} @tab The client is an ODBC client. This changes
+@code{mysqld} to be more ODBC-friendly.
+@end multitable
+@end itemize
+
+@subsubheading Return values
+
+A @code{MYSQL*} connection handle if the connection was successful,
+@code{NULL} if the connection was unsuccessful. For a successful connection,
+the return value is the same as the value of the first parameter, unless you
+pass @code{NULL} for that parameter.
+
+@subsubheading Errors
+
+@table @code
+@item CR_CONN_HOST_ERROR
+Failed to connect to the @strong{MySQL} server.
+
+@item CR_CONNECTION_ERROR
+Failed to connect to the local @strong{MySQL} server.
+
+@item CR_IPSOCK_ERROR
+Failed to create an IP socket.
+
+@item CR_OUT_OF_MEMORY
+Out of memory.
+
+@item CR_SOCKET_CREATE_ERROR
+Failed to create a Unix socket.
+
+@item CR_UNKNOWN_HOST
+Failed to find the IP address for the hostname.
+
+@item CR_VERSION_ERROR
+A protocol mismatch resulted from attempting to connect to a server with a
+client library that uses a different protocol version. This can happen if you
+use a very old client library to connect to a new server that wasn't started
+with the @code{--old-protocol} option.
+
+@item CR_NAMEDPIPEOPEN_ERROR;
+Failed to create a named pipe on Win32.
+
+@item CR_NAMEDPIPEWAIT_ERROR;
+Failed to wait for a named pipe on Win32.
+
+@item CR_NAMEDPIPESETSTATE_ERROR;
+Failed to get a pipe handler on Win32.
+@end table
+
+@subsubheading Example
+
+@example
+MYSQL mysql;
+
+mysql_init(&mysql);
+mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"your_prog_name");
+if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0))
+@{
+ fprintf(stderr, "Failed to connect to database: Error: %s\n",
+ mysql_error(&mysql));
+@}
+@end example
+
+By using @code{mysql_options()} the @strong{MySQL} library will read the
+@code{[client]} and @code{your_prog_name} sections in the @code{my.cnf}
+file which will ensure that your program will work, even if someone has
+set up @strong{MySQL} in some non-standard way.
+
+Note that upon connection, @code{mysql_real_connect()} sets the @code{reconnect}
+flag (part of the MYSQL structure) to a value of @code{1}. This flag indicates,
+in the event that a query cannot be performed because of a lost connection, to
+try reconnecting to the server before giving up.
+
+@findex @code{mysql_real_escape_string()}
+@node mysql_real_escape_string, mysql_real_query, mysql_real_connect, C API functions
+@subsection @code{mysql_real_escape_string()}
+
+@code{unsigned int mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned int length)}
+
+@subsubheading Description
+
+Encodes the string in @code{from} to an escaped SQL string, taking into
+account the current charset of the connection, that can be sent to the
+server in a SQL statement, places the result in @code{to}, and adds a
+terminating null byte. Characters encoded are @code{NUL} (ASCII 0),
+@samp{\n}, @samp{\r}, @samp{\}, @samp{'}, @samp{"} and Control-Z
+(@pxref{Literals}).
+
+The string pointed to by @code{from} must be @code{length} bytes long. You
+must allocate the @code{to} buffer to be at least @code{length*2+1} bytes
+long. (In the worse case, each character may need to be encoded as using two
+bytes, and you need room for the terminating null byte.) When
+@code{mysql_escape_string()} returns, the contents of @code{to} will be a
+null-terminated string. The return value is the length of the encoded
+string, not including the terminating null character.
+
+@subsubheading Example
+
+@example
+char query[1000],*end;
+
+end = strmov(query,"INSERT INTO test_table values(");
+*end++ = '\'';
+end += mysql_real_escape_string(&mysql, end,"What's this",11);
+*end++ = '\'';
+*end++ = ',';
+*end++ = '\'';
+end += mysql_real_escape_string(&mysql, end,"binary data: \0\r\n",16);
+*end++ = '\'';
+*end++ = ')';
+
+if (mysql_real_query(&mysql,query,(unsigned int) (end - query)))
+@{
+ fprintf(stderr, "Failed to insert row, Error: %s\n",
+ mysql_error(&mysql));
+@}
+@end example
+
+The @code{strmov()} function used in the example is included in the
+@code{mysqlclient} library and works like @code{strcpy()} but returns a
+pointer to the terminating null of the first parameter.
+
+@subsubheading Return values
+
+The length of the value placed into @code{to}, not including the
+terminating null character.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_real_query()}
+@node mysql_real_query, mysql_reload, mysql_real_escape_string, C API functions
+@subsection @code{mysql_real_query()}
+
+@code{int mysql_real_query(MYSQL *mysql, const char *query, unsigned int length)}
+
+@subsubheading Description
+
+Executes the SQL query pointed to by @code{query}, which should be a string
+@code{length} bytes long. The query must consist of a single SQL statement.
+You should not add a terminating semicolon (@samp{;}) or @code{\g} to the
+statement.
+
+You @emph{must} use @code{mysql_real_query()} rather than
+@code{mysql_query()} for queries that contain binary data, because binary data
+may contain the @samp{\0} character. In addition, @code{mysql_real_query()}
+is faster than @code{mysql_query()} because it does not call @code{strlen()} on
+the query string.
+
+If you want to know if the query should return a result set or not, you can
+use @code{mysql_field_count()} to check for this.
+@xref{mysql_field_count, @code{mysql_field_count}}.
+
+@subsubheading Return values
+
+Zero if the query was successful. Non-zero if an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_reload()}
+@node mysql_reload, mysql_row_seek, mysql_real_query, C API functions
+@subsection @code{mysql_reload()}
+
+@code{int mysql_reload(MYSQL *mysql)}
+
+@subsubheading Description
+
+Asks the @strong{MySQL} server to reload the grant tables. The
+connected user must have the @strong{reload} privilege.
+
+This function is deprecated. It is preferable to use @code{mysql_query()}
+to issue a SQL @code{FLUSH PRIVILEGES} statement instead.
+
+@subsubheading Return values
+
+Zero for success. Non-zero if an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_row_seek()}
+@node mysql_row_seek, mysql_row_tell, mysql_reload, C API functions
+@subsection @code{mysql_row_seek()}
+
+@code{MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset)}
+
+@subsubheading Description
+Sets the row cursor to an arbitrary row in a query result set. This requires
+that the result set structure contains the entire result of the query, so
+@code{mysql_row_seek()} may be used in conjunction only with
+@code{mysql_store_result()}, not with @code{mysql_use_result()}.
+
+The offset should be a value returned from a call to @code{mysql_row_tell()}
+or to @code{mysql_row_seek()}. This value is not simply a row number; if you
+want to seek to a row within a result set using a row number, use
+@code{mysql_data_seek()} instead.
+
+@subsubheading Return values
+
+The previous value of the row cursor. This value may be passed to a
+subsequent call to @code{mysql_row_seek()}.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_row_tell()}
+@node mysql_row_tell, mysql_select_db, mysql_row_seek, C API functions
+@subsection @code{mysql_row_tell()}
+
+@code{MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result)}
+
+@subsubheading Description
+
+Returns the current position of the row cursor for the last
+@code{mysql_fetch_row()}. This value can be used as an argument to
+@code{mysql_row_seek()}.
+
+You should use @code{mysql_row_tell()} only after @code{mysql_store_result()},
+not after @code{mysql_use_result()}.
+
+@subsubheading Return values
+
+The current offset of the row cursor.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_select_db()}
+@node mysql_select_db, mysql_shutdown, mysql_row_tell, C API functions
+@subsection @code{mysql_select_db()}
+
+@code{int mysql_select_db(MYSQL *mysql, const char *db)}
+
+@subsubheading Description
+
+Causes the database specified by @code{db} to become the default (current)
+database on the connection specified by @code{mysql}. In subsequent queries,
+this database is the default for table references that do not include an
+explicit database specifier.
+
+@code{mysql_select_db()} fails unless the connected user can be authenticated
+as having permission to use the database.
+
+@subsubheading Return values
+
+Zero for success. Non-zero if an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_shutdown()}
+@node mysql_shutdown, mysql_stat, mysql_select_db, C API functions
+@subsection @code{mysql_shutdown()}
+
+@code{int mysql_shutdown(MYSQL *mysql)}
+
+@subsubheading Description
+
+Asks the database server to shutdown. The connected user must have
+@strong{shutdown} privileges.
+
+@subsubheading Return values
+
+Zero for success. Non-zero if an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_stat()}
+@node mysql_stat, mysql_store_result, mysql_shutdown, C API functions
+@subsection @code{mysql_stat()}
+
+@code{char *mysql_stat(MYSQL *mysql)}
+
+@subsubheading Description
+
+Returns a character string containing information similar to that provided by
+the @code{mysqladmin status} command. This includes uptime in seconds and
+the number of running threads, questions, reloads and open tables.
+
+@subsubheading Return values
+
+A character string describing the server status. @code{NULL} if an
+error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_store_result()}
+@node mysql_store_result, mysql_thread_id, mysql_stat, C API functions
+@subsection @code{mysql_store_result()}
+
+@code{MYSQL_RES *mysql_store_result(MYSQL *mysql)}
+
+@subsubheading Description
+
+You must call @code{mysql_store_result()} or @code{mysql_use_result()}
+for every query which successfully retrieves data (@code{SELECT},
+@code{SHOW}, @code{DESCRIBE}, @code{EXPLAIN}).
+
+If you want to know if the query should return a result set or not, you can
+use @code{mysql_field_count()} to check for this.
+@xref{mysql_field_count, @code{mysql_field_count}}.
+
+@code{mysql_store_result()} reads the entire result of a query to the client,
+allocates a @code{MYSQL_RES} structure, and places the result into this
+structure.
+
+@code{mysql_store_results()} returns a null pointer if the query didn't return
+a result sets (If the query was for example an @code{INSERT} statement).
+
+@code{mysql_store_results()} returns also null pointer if reading of the
+result set failed. You can check if you got an error by checking if
+@code{mysql_error()} doesn't return a null pointer, if
+@code{mysql_errno()} returns <> 0 or if @code{mysql_field_count()}
+returns <> 0.
+
+An empty result set is returned if there are no rows returned. (An empty
+result set differs from a null pointer as a return value.)
+
+Once you have called @code{mysql_store_result()} and got a result back
+which isn't a null pointer, you may call @code{mysql_num_rows()} to find
+out how many rows are in the result set.
+
+You can call @code{mysql_fetch_row()} to fetch rows from the result set,
+or @code{mysql_row_seek()} and @code{mysql_row_tell()} to obtain or
+set the current row position within the result set.
+
+You must call @code{mysql_free_result()} once you are done with the result
+set.
+
+@xref{NULL mysql_store_result, , @code{NULL mysql_store_result()}}.
+
+@subsubheading Return values
+
+A @code{MYSQL_RES} result structure with the results. @code{NULL} if
+an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_OUT_OF_MEMORY
+Out of memory.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@findex @code{mysql_thread_id()}
+@node mysql_thread_id, mysql_use_result, mysql_store_result, C API functions
+@subsection @code{mysql_thread_id()}
+
+@code{unsigned long mysql_thread_id(MYSQL *mysql)}
+
+@subsubheading Description
+
+Returns the thread ID of the current connection. This value can be used as
+an argument to @code{mysql_kill()} to kill the thread.
+
+If the connection is lost and you reconnect with @code{mysql_ping()}, the
+thread ID will change. This means you should not get the thread ID and store
+it for later, you should get it when you need it.
+
+@subsubheading Return values
+
+The thread ID of the current connection.
+
+@subsubheading Errors
+None.
+
+@findex @code{mysql_use_result()}
+@node mysql_use_result, NULL mysql_store_result, mysql_thread_id, C API functions
+@subsection @code{mysql_use_result()}
+
+@code{MYSQL_RES *mysql_use_result(MYSQL *mysql)}
+
+@subsubheading Description
+
+You must call @code{mysql_store_result()} or @code{mysql_use_result()} for
+every query which successfully retrieves data (@code{SELECT}, @code{SHOW},
+@code{DESCRIBE}, @code{EXPLAIN}).
+
+@code{mysql_use_result()} initiates a result set retrieval but does not
+actually read the result set into the client like @code{mysql_store_result()}
+does. Instead, each row must be retrieved individually by making calls to
+@code{mysql_fetch_row()}. This reads the result of a query directly from the
+server without storing it in a temporary table or local buffer, which is
+somewhat faster and uses much less memory than @code{mysql_store_result()}.
+The client will only allocate memory for the current row and a communication
+buffer that may grow up to @code{max_allowed_packet} bytes.
+
+On the other hand, you shouldn't use @code{mysql_use_result()} if you are
+doing a lot of processing for each row on the client side, or if the output
+is sent to a screen on which the user may type a @code{^S} (stop scroll).
+This will tie up the server and prevent other threads from updating any
+tables from which the data is being fetched.
+
+When using @code{mysql_use_result()}, you must execute
+@code{mysql_fetch_row()} until a @code{NULL} value is returned, otherwise the
+unfetched rows will be returned as part of the result set for your next
+query. The C API will give the error @code{Commands out of sync; You can't
+run this command now} if you forget to do this!
+
+You may not use @code{mysql_data_seek()}, @code{mysql_row_seek()},
+@code{mysql_row_tell()}, @code{mysql_num_rows()} or
+@code{mysql_affected_rows()} with a result returned from
+@code{mysql_use_result()}, nor may you issue other queries until the
+@code{mysql_use_result()} has finished. (However, after you have fetched all
+the rows, @code{mysql_num_rows()} will accurately return the number of rows
+fetched.)
+
+You must call @code{mysql_free_result()} once you are done with the result
+set.
+
+@subsubheading Return values
+
+A @code{MYSQL_RES} result structure. @code{NULL} if an error occurred.
+
+@subsubheading Errors
+
+@table @code
+@item CR_COMMANDS_OUT_OF_SYNC
+Commands were executed in an improper order.
+@item CR_OUT_OF_MEMORY
+Out of memory.
+@item CR_SERVER_GONE_ERROR
+The @strong{MySQL} server has gone away.
+@item CR_SERVER_LOST
+The connection to the server was lost during the query.
+@item CR_UNKNOWN_ERROR
+An unknown error occurred.
+@end table
+
+@node NULL mysql_store_result, Query results, mysql_use_result, C API functions
+@subsection Why is it that after @code{mysql_query()} returns success, @code{mysql_store_result()} sometimes returns @code{NULL?}
+
+It is possible for @code{mysql_store_result()} to return @code{NULL}
+following a successful call to @code{mysql_query()}. When this happens, it
+means one of the following conditions occurred:
+
+@itemize @bullet
+@item
+There was a @code{malloc()} failure (for example, if the result set was too
+large).
+
+@item
+The data couldn't be read (an error occurred on the connection).
+
+@item
+The query returned no data (e.g., it was an @code{INSERT}, @code{UPDATE}
+or @code{DELETE}).
+@end itemize
+
+You can always check whether or not the statement should have produced a
+non-empty result by calling @code{mysql_field_count()}. If
+@code{mysql_field_count()} returns zero, the result is empty and the last
+query was a statement that does not return values (for example, an
+@code{INSERT} or a @code{DELETE}). If @code{mysql_field_count()} returns a
+non-zero value, the statement should have produced a non-empty result.
+See the description of the @code{mysql_field_count()} function for an
+example.
+
+You can test for an error by calling @code{mysql_error()} or
+@code{mysql_errno()}.
+
+@node Query results, Getting unique ID, NULL mysql_store_result, C API functions
+@subsection What results can I get from a query?
+
+In addition to the result set returned by a query, you can also get the
+following information:
+
+@itemize @bullet
+@item
+@code{mysql_affected_rows()} returns the number of rows affected by the last
+query when doing an @code{INSERT}, @code{UPDATE} or @code{DELETE}. An
+exception is that if @code{DELETE} is used without a @code{WHERE} clause, the
+table is recreated empty, which is much faster! In this case,
+@code{mysql_affected_rows()} returns zero for the number of records
+affected.
+
+@item
+@code{mysql_num_rows()} returns the number of rows in a result set. With
+@code{mysql_store_result()}, @code{mysql_num_rows()} may be called as soon as
+@code{mysql_store_result()} returns. With @code{mysql_use_result()},
+@code{mysql_num_rows()} may be called only after you have fetched all the
+rows with @code{mysql_fetch_row()}.
+
+@item
+@code{mysql_insert_id()} returns the ID generated by the last
+query that inserted a row into a table with an @code{AUTO_INCREMENT} index.
+@xref{mysql_insert_id, , @code{mysql_insert_id()}}.
+
+@item
+Some queries (@code{LOAD DATA INFILE ...}, @code{INSERT INTO
+... SELECT ...}, @code{UPDATE}) return additional info. The result is
+returned by @code{mysql_info()}. See the description for @code{mysql_info()}
+for the format of the string that it returns. @code{mysql_info()} returns a
+@code{NULL} pointer if there is no additional information.
+@end itemize
+
+@node Getting unique ID, C API linking problems, Query results, C API functions
+@subsection How can I get the unique ID for the last inserted row?
+
+If you insert a record in a table containing a column that has the
+@code{AUTO_INCREMENT} attribute, you can get the most recently generated
+ID by calling the @code{mysql_insert_id()} function.
+
+You can also retrieve the ID by using the @code{LAST_INSERT_ID()} function in
+a query string that you pass to @code{mysql_query()}.
+
+You can check if an @code{AUTO_INCREMENT} index is used by executing
+the following code. This also checks if the query was an @code{INSERT} with
+an @code{AUTO_INCREMENT} index:
+
+@example
+if (mysql_error(&mysql)[0] == 0 &&
+ mysql_num_fields(result) == 0 &&
+ mysql_insert_id(&mysql) != 0)
+@{
+ used_id = mysql_insert_id(&mysql);
+@}
+@end example
+
+The most recently generated ID is maintained in the server on a
+per-connection basis. It will not be changed by another client. It will not
+even be changed if you update another @code{AUTO_INCREMENT} column with a
+non-magic value (that is, a value that is not @code{NULL} and not @code{0}).
+
+If you want to use the ID that was generated for one table and insert
+it into a second table, you can use SQL statements like this:
+
+@example
+INSERT INTO foo (auto,text)
+ VALUES(NULL,'text'); # generate ID by inserting NULL
+INSERT INTO foo2 (id,text)
+ VALUES(LAST_INSERT_ID(),'text'); # use ID in second table
+@end example
+
+@node C API linking problems, Thread-safe clients, Getting unique ID, C API functions
+@subsection Problems linking with the C API
+
+When linking with the C API, the following errors may occur on some systems:
+
+@example
+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
+@end example
+
+If this happens on your system, you must include the math library by
+adding @code{-lm} to the end of the compile/link line.
+
+@node Thread-safe clients, , C API linking problems, C API functions
+@subsection How to make a thread-safe client
+
+The client library is ``almost'' thread-safe. The biggest problem is
+that the subroutines in @file{net.c} that read from sockets are not
+interrupt-safe. This was done with the thought that you might want to
+have your own alarm that can break a long read to a server. If you
+install an interrupt handlers for the @code{SIGPIPE} interrupt,
+the socket handling should be thread safe.
+
+In the standard binaries we distribute on our web site, the client libraries
+are not normally compiled with the thread safe option.
+
+To get a really thread-safe client where you can interrupt the client
+from other threads and set timeouts when talking with the MySQL server,
+you should use the @code{-lmysys}, @code{-lstring} and @code{-ldbug}
+libraries and the @code{net_serv.o} code that the server uses.
+
+If you don't need interrupts or timeouts you can just compile the client
+library @code{(mysqlclient)} to be thread safe and use this. In this
+case you don't have to worry about the @code{net_serv.o} object file or
+the other @strong{MySQL} libraries.
+
+When using a threaded client and you want to use timeouts and interrupts,
+you can make great use of the routines in the @file{thr_alarm.c} file.
+If you are using routines from the @code{mysys} library, the only thing
+you must remember is to call @code{my_init()} first!
+
+All functions except @code{mysql_real_connect()} are by default
+thread-safe. The following notes describe how to compile a thread-safe
+client library and use it in a thread-safe manner. (The notes below for
+@code{mysql_real_connect()} actually apply to @code{mysql_connect()} as
+well, but because @code{mysql_connect()} is deprecated, you should be
+using @code{mysql_real_connect()} anyway.)
+
+To make @code{mysql_real_connect()} thread-safe, you must recompile the
+client library with this command:
+
+@example
+shell> ./configure --enable-thread-safe-client
+@end example
+
+This will ensure that the client library will use the header files required
+for thread safe programs and also that @code{mysql_real_connect()} will use
+a thread safe version of the @code{gethostbyname()} call.
+
+You may get some errors because of undefined symbols when linking the
+standard client, because the pthread libraries are not included by
+default.
+
+The resulting @file{libmysqlclient.a} library is now thread-safe. What this
+means is that client code is thread-safe as long as two threads don't query
+the same connection handle returned by @code{mysql_real_connect()} at the
+same time; the client/server protocol allows only one request at a time on a
+given connection. If you want to use multiple threads on the same
+connection, you must have a mutex lock around your @code{mysql_query()} and
+@code{mysql_store_result()} call combination. Once
+@code{mysql_store_result()} is ready, the lock can be released and other
+threads may query the same connection. (In other words, different threads
+can use different @code{MYSQL_RES} pointers that were created with
+@code{mysql_store_result()}, as long as they use the proper locking
+protocol.) If you program with POSIX threads, you can use
+@code{pthread_mutex_lock()} and @code{pthread_mutex_unlock()} to establish
+and release a mutex lock.
+
+If you used @code{mysql_use_result()} rather than @code{mysql_store_result()},
+the lock would need to surround @code{mysql_use_result()} and the calls
+to @code{mysql_fetch_row()}. However, it really is best for threaded
+clients not to use @code{mysql_use_result()}.
+
+@node Perl, Eiffel, C API functions, Clients
+@section MySQL Perl API
+
+This section documents the Perl @code{DBI} interface. The former interface
+was called @code{mysqlperl}. @code{DBI}/@code{DBD} now is the
+recommended Perl interface, so @code{mysqlperl} is obsolete and is not
+documented here.
+
+@menu
+* DBI with DBD:: @code{DBI} with @code{DBD::mysql}
+* Perl DBI Class:: The @code{DBI} interface
+* DBI-info:: More @code{DBI}/@code{DBD} information
+@end menu
+
+@node DBI with DBD, Perl DBI Class, Perl, Perl
+@subsection @code{DBI} with @code{DBD::mysql}
+
+@code{DBI} is a generic interface for many databases. That means that
+you can write a script that works with many different database engines
+without change. You need a DataBase Driver (DBD) defined for each
+database type. For @strong{MySQL}, this driver is called
+@code{DBD::mysql}.
+
+For more information on the Perl5 DBI, please visit the @code{DBI} web
+page and read the documentation:
+@example
+@uref{http://www.symbolstone.org/technology/perl/DBI/index.html}
+@end example
+For more information on Object Oriented Programming
+(OOP) as defined in Perl5, see the Perl OOP page:
+@example
+@uref{http://language.perl.com/info/documentation.html}
+@end example
+
+Installation instructions for @strong{MySQL} Perl support are given in
+@ref{Perl support}.
+
+@cindex @code{DBI} Perl module
+@node Perl DBI Class, DBI-info, DBI with DBD, Perl
+@subsection The @code{DBI} interface
+
+@noindent
+@strong{Portable DBI methods}
+
+@multitable @columnfractions .3 .7
+@item @code{connect} @tab Establishes a connection to a database server.
+@item @code{disconnect} @tab Disconnects from the database server.
+@item @code{prepare} @tab Prepares a SQL statement for execution.
+@item @code{execute} @tab Executes prepared statements.
+@item @code{do} @tab Prepares and executes a SQL statement.
+@item @code{quote} @tab Quotes string or @code{BLOB} values to be inserted.
+@item @code{fetchrow_array} @tab Fetches the next row as an array of fields.
+@item @code{fetchrow_arrayref} @tab Fetches next row as a reference array of fields.
+@item @code{fetchrow_hashref} @tab Fetches next row as a reference to a hashtable.
+@item @code{fetchall_arrayref} @tab Fetches all data as an array of arrays.
+@item @code{finish} @tab Finishes a statement and lets the system free resources.
+@item @code{rows} @tab Returns the number of rows affected.
+@item @code{data_sources} @tab Returns an array of databases available on localhost.
+@item @code{ChopBlanks} @tab Controls whether @code{fetchrow_*} methods trim spaces.
+@item @code{NUM_OF_PARAMS} @tab The number of placeholders in the prepared statement.
+@item @code{NULLABLE} @tab Which columns can be @code{NULL}.
+@item @code{trace} @tab Perform tracing for debugging.
+@end multitable
+
+@noindent
+@strong{MySQL-specific methods}
+
+@multitable @columnfractions .3 .7
+@item @code{insertid} @tab The latest @code{AUTO_INCREMENT} value.
+@item @code{is_blob} @tab Which column are @code{BLOB} values.
+@item @code{is_key} @tab Which columns are keys.
+@item @code{is_num} @tab Which columns are numeric.
+@item @code{is_pri_key} @tab Which columns are primary keys.
+@item @code{is_not_null} @tab Which columns CANNOT be @code{NULL}. See @code{NULLABLE}.
+@item @code{length} @tab Maximum possible column sizes.
+@item @code{max_length} @tab Maximum column sizes actually present in result.
+@item @code{NAME} @tab Column names.
+@item @code{NUM_OF_FIELDS} @tab Number of fields returned.
+@item @code{table} @tab Table names in returned set.
+@item @code{type} @tab All column types.
+@end multitable
+
+The Perl methods are described in more detail in the following sections.
+Variables used for method return values have these meanings:
+
+@table @code
+@item $dbh
+Database handle
+
+@item $sth
+Statement handle
+
+@item $rc
+Return code (often a status)
+
+@item $rv
+Return value (often a row count)
+@end table
+
+@noindent
+@strong{Portable DBI methods}
+
+@table @code
+
+@findex DBI->connect()
+@findex connect() DBI method
+@item connect($data_source, $username, $password)
+Use the @code{connect} method to make a database connection to the data
+source. The @code{$data_source} value should begin with
+@code{DBI:driver_name:}.
+Example uses of @code{connect} with the @code{DBD::mysql} driver:
+@example
+$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);
+@end example
+If the user name and/or password are undefined, @code{DBI} uses the
+values of the @code{DBI_USER} and @code{DBI_PASS} environment variables,
+respectively. If you don't specify a hostname, it defaults to
+@code{'localhost'}. If you don't specify a port number, it defaults to the
+default @strong{MySQL} port (@value{default_port}).
+
+As of @code{Msql-Mysql-modules} version 1.2009,
+the @code{$data_source} value allows certain modifiers:
+
+@table @code
+@item mysql_read_default_file=file_name
+Read @file{filename} as an option file. For information on option files,
+see @ref{Option files}.
+
+@item mysql_read_default_group=group_name
+The default group when reading an option file is normally the
+@code{[client]} group. By specifying the @code{mysql_read_default_group}
+option, the default group becomes the @code{[group_name]} group.
+
+@item mysql_compression=1
+Use compressed communication between the client and server (@strong{MySQL}
+3.22.3 or later).
+
+@item mysql_socket=/path/to/socket
+Specify the pathname of the Unix socket that is used to connect
+to the server (@strong{MySQL} 3.21.15 or later).
+@end table
+
+Multiple modifiers may be given; each must be preceded by a semicolon.
+
+For example, if you want to avoid hardcoding the user name and password into
+a @code{DBI} script, you can take them from the user's @file{~/.my.cnf}
+option file instead by writing your @code{connect} call like this:
+
+@example
+$dbh = DBI->connect("DBI:mysql:$database"
+ . ";mysql_read_default_file=$ENV@{HOME@}/.my.cnf",
+ $user, $password);
+@end example
+
+This call will read options defined for the @code{[client]} group in the
+option file. If you wanted to do the same thing, but use options specified
+for the @code{[perl]} group as well, you could use this:
+
+@example
+$dbh = DBI->connect("DBI:mysql:$database"
+ . ";mysql_read_default_file=$ENV@{HOME@}/.my.cnf"
+ . ";mysql_read_default_group=perl",
+ $user, $password);
+@end example
+
+@findex DBI->disconnect
+@findex disconnect DBI method
+@item disconnect
+The @code{disconnect} method disconnects the database handle from the database.
+This is typically called right before you exit from the program.
+Example:
+@example
+$rc = $dbh->disconnect;
+@end example
+
+@findex DBI->prepare()
+@findex prepare() DBI method
+@item prepare($statement)
+Prepares a SQL statement for execution by the database engine
+and returns a statement handle @code{($sth)} which you can use to invoke
+the @code{execute} method.
+Typically you handle @code{SELECT} statements (and @code{SELECT}-like statements
+such as @code{SHOW}, @code{DESCRIBE} and @code{EXPLAIN}) by means of
+@code{prepare} and @code{execute}.
+Example:
+@example
+$sth = $dbh->prepare($statement)
+ or die "Can't prepare $statement: $dbh->errstr\n";
+@end example
+
+@findex DBI->execute
+@findex execute DBI method
+@item execute
+The @code{execute} method executes a prepared statement. For
+non-@code{SELECT} statements, @code{execute} returns the number of rows
+affected. If no rows are affected, @code{execute} returns @code{"0E0"},
+which Perl treats as zero but regards as true. If an error occurs,
+@code{execute} returns @code{undef}. For @code{SELECT} statements,
+@code{execute} only starts the SQL query in the database; you need to use one
+of the @code{fetch_*} methods described below to retrieve the data.
+Example:
+@example
+$rv = $sth->execute
+ or die "can't execute the query: $sth->errstr;
+@end example
+
+@findex DBI->do()
+@findex do() DBI method
+@item do($statement)
+The @code{do} method prepares and executes a SQL statement and returns the
+number of rows affected. If no rows are affected, @code{do} returns
+@code{"0E0"}, which Perl treats as zero but regards as true. This method is
+generally used for non-@code{SELECT} statements which cannot be prepared in
+advance (due to driver limitations) or which do not need to executed more
+than once (inserts, deletes, etc.). Example:
+@example
+$rv = $dbh->do($statement)
+ or die "Can't execute $statement: $dbh- >errstr\n";
+@end example
+
+Generally the 'do' statement is MUCH faster (and is preferable)
+than prepare/execute for statements that doesn't contain parameters.
+
+@findex DBI->quote()
+@findex quote() DBI method
+@cindex Quoting strings
+@cindex Strings, quoting
+@item quote($string)
+The @code{quote} method is used to "escape" any special characters contained in
+the string and to add the required outer quotation marks.
+Example:
+@example
+$sql = $dbh->quote($string)
+@end example
+
+@findex DBI->fetchrow_array
+@findex fetchrow_array DBI method
+@item fetchrow_array
+This method fetches the next row of data and returns it as an array of
+field values. Example:
+@example
+while(@@row = $sth->fetchrow_array) @{
+ print qw($row[0]\t$row[1]\t$row[2]\n);
+@}
+@end example
+
+@findex DBI->fetchrow_arrayref
+@findex fetchrow_arrayref DBI method
+@item fetchrow_arrayref
+This method fetches the next row of data and returns it as a reference
+to an array of field values. Example:
+@example
+while($row_ref = $sth->fetchrow_arrayref) @{
+ print qw($row_ref->[0]\t$row_ref->[1]\t$row_ref->[2]\n);
+@}
+@end example
+
+@findex DBI->fetchrow_hashref
+@findex fetchrow_hashref DBI method
+@item 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:
+@example
+while($hash_ref = $sth->fetchrow_hashref) @{
+ print qw($hash_ref->@{firstname@}\t$hash_ref->@{lastname@}\t\
+ $hash_ref- > title@}\n);
+@}
+@end example
+
+@findex DBI->fetchall_arrayref
+@findex fetchall_arrayref DBI method
+@item 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 references to arrays
+for each row. You access or print the data by using a nested
+loop. Example:
+@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";
+@}
+@end example
+
+@findex DBI->finish
+@findex finish DBI method
+@item finish
+Indicates that no more data will be fetched from this statement
+handle. You call this method to free up the statement handle and any
+system resources associated with it. Example:
+@example
+$rc = $sth->finish;
+@end example
+
+@findex DBI->rows
+@findex rows DBI method
+@item rows
+Returns the number of rows changed (updated, deleted, etc.) by the last
+command. This is usually used after a non-@code{SELECT} @code{execute}
+statement. Example:
+@example
+$rv = $sth->rows;
+@end example
+
+@findex DBI->@{NULLABLE@}
+@findex NULLABLE DBI method
+@item NULLABLE
+Returns a reference to an array of boolean values; for each element of
+the array, a value of TRUE indicates that this
+column may contain @code{NULL} values.
+Example:
+@example
+$null_possible = $sth->@{NULLABLE@};
+@end example
+
+@findex DBI->@{NUM_OF_FIELDS@}
+@findex NUM_OF_FIELDS DBI method
+@item NUM_OF_FIELDS
+This attribute indicates
+the number of fields returned by a @code{SELECT} or @code{SHOW FIELDS}
+statement. You may use this for checking whether a statement returned a
+result: A zero value indicates a non-@code{SELECT} statement like
+@code{INSERT}, @code{DELETE} or @code{UPDATE}.
+Example:
+@example
+$nr_of_fields = $sth->@{NUM_OF_FIELDS@};
+@end example
+
+@findex DBI->data_sources()
+@findex data_sources() DBI method
+@item data_sources($driver_name)
+This method returns an array containing names of databases available to the
+@strong{MySQL} server on the host @code{'localhost'}.
+Example:
+@example
+@@dbs = DBI->data_sources("mysql");
+@end example
+
+@findex DBI->@{ChopBlanks@}
+@findex ChopBlanks DBI method
+@item ChopBlanks
+This attribute determines whether the @code{fetchrow_*} methods will chop
+leading and trailing blanks from the returned values.
+Example:
+@example
+$sth->@{'ChopBlanks'@} =1;
+@end example
+
+@findex DBI->trace
+@findex trace DBI method
+@item trace($trace_level)
+@itemx trace($trace_level, $trace_filename)
+The @code{trace} method enables or disables tracing. When invoked as a
+@code{DBI} class method, it affects tracing for all handles. When invoked as
+a database or statement handle method, it affects tracing for the given
+handle (and any future children of the handle). Setting @code{$trace_level}
+to 2 provides detailed trace information. Setting @code{$trace_level} to 0
+disables tracing. Trace output goes to the standard error output by
+default. If @code{$trace_filename} is specified, the file is opened in
+append mode and output for @emph{all} traced handles is written to that
+file. Example:
+@example
+DBI->trace(2); # trace everything
+DBI->trace(2,"/tmp/dbi.out"); # trace everything to /tmp/dbi.out
+$dth->trace(2); # trace this database handle
+$sth->trace(2); # trace this statement handle
+@end example
+
+@tindex DBI_TRACE environment variable
+@tindex Environment variable, DBI_TRACE
+You can also enable @code{DBI} tracing by setting the @code{DBI_TRACE}
+environment variable. Setting it to a numeric value is equivalent to calling
+@code{DBI->(value)}. Setting it to a pathname is equivalent to calling
+@code{DBI->(2,value)}.
+
+@end table
+
+@noindent
+@strong{MySQL-specific methods}
+
+The methods shown below are @strong{MySQL}-specific and not part of the
+@code{DBI} standard. Several of them are now deprecated:
+@code{is_blob}, @code{is_key}, @code{is_num}, @code{is_pri_key},
+@code{is_not_null}, @code{length}, @code{max_length}, and @code{table}.
+Where @code{DBI}-standard alternatives exist, they are noted below.
+
+@table @code
+@findex DBI->@{insertid@}
+@findex insertid DBI method
+@tindex AUTO_INCREMENT, using with DBI
+@item insertid
+If you use the @code{AUTO_INCREMENT} feature of @strong{MySQL}, the new
+auto-incremented values will be stored here.
+Example:
+@example
+$new_id = $sth->@{insertid@};
+@end example
+
+As an alternative, you can use @code{$dbh->@{'mysql_insertid'@}}.
+
+@findex DBI->@{is_blob@}
+@findex is_blob DBI method
+@item is_blob
+Returns a reference to an array of boolean values; for each element of the
+array, a value of TRUE indicates that the
+respective column is a @code{BLOB}.
+Example:
+@example
+$keys = $sth->@{is_blob@};
+@end example
+
+@findex DBI->@{is_key@}
+@findex is_key DBI method
+@item is_key
+Returns a reference to an array of boolean values; for each element of the
+array, a value of TRUE indicates that the
+respective column is a key.
+Example:
+@example
+$keys = $sth->@{is_key@};
+@end example
+
+@findex DBI->@{is_num@}
+@findex is_num DBI method
+@item is_num
+Returns a reference to an array of boolean values; for each element of the
+array, a value of TRUE indicates that the
+respective column contains numeric values.
+Example:
+@example
+$nums = $sth->@{is_num@};
+@end example
+
+@findex DBI->@{is_pri_key@}
+@findex is_pri_key DBI method
+@item is_pri_key
+Returns a reference to an array of boolean values; for each element of the
+array, a value of TRUE indicates that the respective column is a primary key.
+Example:
+@example
+$pri_keys = $sth->@{is_pri_key@};
+@end example
+
+@findex DBI->@{is_not_null@}
+@findex is_not_null DBI method
+@item is_not_null
+Returns a reference to an array of boolean values; for each element of the
+array, a value of FALSE indicates that this column may contain @code{NULL}
+values.
+Example:
+@example
+$not_nulls = $sth->@{is_not_null@};
+@end example
+
+@code{is_not_null} is deprecated; it is preferable to use the
+@code{NULLABLE} attribute (described above), because that is a DBI standard.
+
+@findex DBI->@{length@}
+@findex length DBI method
+@findex DBI->@{max_length@}
+@findex max_length DBI method
+@item length
+@itemx max_length
+Each of these methods returns a reference to an array of column sizes. The
+@code{length} array indicates the maximum possible sizes that each column may
+be (as declared in the table description). The @code{max_length} array
+indicates the maximum sizes actually present in the result table. Example:
+
+@example
+$lengths = $sth->@{length@};
+$max_lengths = $sth->@{max_length@};
+@end example
+
+@findex DBI->@{NAME@}
+@findex NAME DBI method
+@item NAME
+Returns a reference to an array of column names.
+Example:
+@example
+$names = $sth->@{NAME@};
+@end example
+
+@findex DBI->@{table@}
+@findex table DBI method
+@item table
+Returns a reference to an array of table names.
+Example:
+@example
+$tables = $sth->@{table@};
+@end example
+
+@findex DBI->@{type@}
+@findex type DBI method
+@item type
+Returns a reference to an array of column types.
+Example:
+@example
+$types = $sth->@{type@};
+@end example
+
+@end table
+
+@node DBI-info, , Perl DBI Class, Perl
+@subsection More @code{DBI}/@code{DBD} information
+
+You can use the @code{perldoc} command to get more information about
+@code{DBI}.
+
+@example
+perldoc DBI
+perldoc DBI::FAQ
+perldoc DBD::mysql
+@end example
+
+You can also use the @code{pod2man}, @code{pod2html}, etc., tools to
+translate to other formats.
+
+And of course you can find the latest @code{DBI} information at
+the @code{DBI} web page:
+@example
+@uref{http://www.symbolstone.org/technology/perl/DBI/index.html}
+@end example
+
+@node Eiffel, Java, Perl, Clients
+@section MySQL Eiffel wrapper
+
+The @strong{MySQL} @uref{http://www.mysql.com/Downloads/Contrib/,Contrib directory}
+contains an Eiffel wrapper written by Michael Ravits.
+
+You can also find this at:
+@url{http://www.netpedia.net/hosting/newplayer/}
+
+@node Java, PHP, Eiffel, Clients
+@section MySQL Java connectivity (JDBC)
+
+There are 2 supported JDBC drivers for @strong{MySQL} (the twz and mm driver).
+You can find a copy of these at @uref{http://www.mysql.com/Downloads/Contrib/}.
+For documentation consult any JDBC documentation and the
+drivers own documentation for @strong{MySQL} specific features.
+
+@node PHP, Cplusplus, Java, Clients
+@section MySQL PHP API
+
+PHP is a server-side, HTML embedded scripting language that may be used to
+create dynamic web pages. It contains support for accessing several
+databases, including @strong{MySQL}. PHP may be run as a separate program,
+or compiled as a module for use with the Apache web server.
+
+The distribution and documentation are available at the
+@uref{http://www.php.net/, PHP website}.
+
+@menu
+* PHP problems:: Common problems with MySQL and PHP
+@end menu
+
+@node PHP problems, , PHP, PHP
+@subsection Common problems with MySQL and PHP
+
+@itemize @bullet
+@item Error: "Maximum Execution Time Exeeded"
+This is a PHP limit; Go into the @file{php3.ini} file and set the maximum
+execution time up from 30 seconds to something higher, as needed.
+It is also not a bad idea to double the ram allowed per script to 16 instead of
+8 MB.
+@item Error: "Fatal error: Call to unsupported or undefined function mysql_connect() in .."
+This means that your PHP version isn't compiled with @strong{MySQL} support.
+You can either compile a dynamic @strong{MySQL} module and load it into PHP or
+recompile PHP with built-in @code{MySQL} support. This is described in
+detail in the PHP manual.
+@end itemize
+
+@node Cplusplus, Python, PHP, Clients
+@section MySQL C++ APIs
+
+Two API's are available in the @strong{MySQL}
+@uref{http://www.mysql.com/Contrib/,Contrib directory}.
+
+@node Python, Tcl, Cplusplus, Clients
+@section MySQL Python APIs
+
+The @strong{MySQL} @uref{http://www.mysql.com/Contrib/,Contrib directory}
+contains a Python
+interface written by Joseph Skinner.
+
+You can also use the Python interface to iODBC to access a
+@strong{MySQL} server.
+@uref{http://starship.skyport.net/~lemburg/,mxODBC}
+
+@node Tcl, , Python, Clients
+@section MySQL Tcl APIs
+
+@uref{http://www.binevolve.com/~tdarugar/tcl-sql/, Tcl at binevolve}.
+The
+@uref{http://www.mysql.com/Contrib,Contrib directory} contains a Tcl
+interface that is based on msqltcl 1.50.
+
+@node Comparisons, MySQL internals, Clients, Top
+@chapter How MySQL compares to other databases
+
+@menu
+* Compare mSQL:: How @strong{MySQL} compares to @code{mSQL}
+* Compare PostgreSQL:: How @strong{MySQL} compares with PostgreSQL
+@end menu
+
+@node Compare mSQL, Compare PostgreSQL, Comparisons, Comparisons
+@section How MySQL compares to @code{mSQL}
+
+This section has been written by the @strong{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
+@uref{http://www.mysql.com/information/crash-me.php, @code{crash-me} web page}.
+
+@table @strong
+@item Performance
+
+For a true comparison of speed, consult the growing @strong{MySQL} benchmark
+suite. @xref{Benchmarks}.
+
+Because there is no thread creation overhead, a small parser, few features and
+simple security, @code{mSQL} should be quicker at:
+
+@itemize @bullet
+@item
+Tests that perform repeated connects and disconnects, running a very simple
+query during each connection.
+@item
+@code{INSERT} operations into very simple tables with few columns and keys.
+@item
+@code{CREATE TABLE} and @code{DROP TABLE}.
+@item
+@code{SELECT} on something that isn't an index. (A table scan is very
+easy.)
+@end itemize
+
+Because these operations are so simple, it is hard to be better at them when
+you have a higher startup overhead. After the connection is established,
+@strong{MySQL} should perform much better.
+
+On the other hand, @strong{MySQL} is much faster than @code{mSQL} (and
+most other SQL implementions) on the following:
+
+@itemize @bullet
+@item
+Complex @code{SELECT} operations.
+@item
+Retrieving large results (@strong{MySQL} has a better, faster and safer
+protocol).
+@item
+Tables with variable-length strings, because @strong{MySQL} has more efficent
+handling and can have indexes on @code{VARCHAR} columns.
+@item
+Handling tables with many columns.
+@item
+Handling tables with large record lengths.
+@item
+@code{SELECT} with many expressions.
+@item
+@code{SELECT} on large tables.
+@item
+Handling many connections at the same time. @strong{MySQL} is fully
+multi-threaded. Each connection has its own thread, which means that
+no thread has to wait for another (unless a thread is modifying
+a table another thread wants to access.) In @code{mSQL}, once one connection
+is established, all others must wait until the first has finished, regardless
+of whether the connection is running a query that is short or long. When the
+first connection terminates, the next can be served, while all the others wait
+again, etc.
+@item
+Joins.
+@code{mSQL} can become pathologically slow if you change the order of tables
+in a @code{SELECT}. In the benchmark suite, a time more than 15000 times
+slower than @strong{MySQL} was seen. This is due to @code{mSQL}'s lack of a
+join optimizer to order tables in the optimal order. However, if you put the
+tables in exactly the right order in @code{mSQL}2 and the @code{WHERE} is
+simple and uses index columns, the join will be relatively fast!
+@xref{Benchmarks}.
+@item
+@code{ORDER BY} and @code{GROUP BY}.
+@item
+@code{DISTINCT}.
+@item
+Using @code{TEXT} or @code{BLOB} columns.
+@end itemize
+
+@item SQL Features
+
+@itemize @bullet
+@item @code{GROUP BY} and @code{HAVING}.
+@code{mSQL} does not support @code{GROUP BY} at all.
+@strong{MySQL} supports a full @code{GROUP BY} with both @code{HAVING} and
+the following functions: @code{COUNT()}, @code{AVG()}, @code{MIN()},
+@code{MAX()}, @code{SUM()} and @code{STD()}. @code{COUNT(*)} is optimized to
+return very quickly if the @code{SELECT} retrieves from one table, no other
+columns are retrieved and there is no @code{WHERE} clause. @code{MIN()} and
+@code{MAX()} may take string arguments.
+
+@item @code{INSERT} and @code{UPDATE} with calculations.
+@strong{MySQL} can do calculations in an @code{INSERT} or @code{UPDATE}.
+For example:
+@example
+mysql> UPDATE SET x=x*10+y WHERE x<20;
+@end example
+
+@item Aliasing.
+@strong{MySQL} has column aliasing.
+
+@item Qualifying column names.
+In @strong{MySQL}, if a column name is unique among the tables used in a
+query, you do not have to use the full qualifier.
+
+@item @code{SELECT} with functions.
+@strong{MySQL} has many functions (too many to list here; see @ref{Functions}).
+
+@end itemize
+
+@item Disk space efficiency
+That is, how small can you make your tables?
+
+@strong{MySQL} has very precise types, so you can create tables that take
+very little space. An example of a useful @strong{MySQL} datatype is the
+@code{MEDIUMINT} that is 3 bytes long. If you have 100,000,000 records,
+saving even one byte per record is very important.
+
+@code{mSQL2} has a more limited set of column types, so it is
+more difficult to get small tables.
+@item Stability
+This is harder to judge objectively. For a discussion of @strong{MySQL}
+stability, see @ref{Stability}.
+
+We have no experience with @code{mSQL} stability, so we cannot say
+anything about that.
+
+@item Price
+Another important issue is the license. @strong{MySQL} has a
+more flexible license than @code{mSQL}, and is also less expensive than
+@code{mSQL}. Whichever product you choose to use, remember to at least
+consider paying for a license or email support. (You are required to get
+a license if you include @strong{MySQL} with a product that you sell,
+of course.)
+
+@item Perl interfaces
+@strong{MySQL} has basically the same interfaces to Perl as @code{mSQL} with
+some added features.
+
+@item JDBC (Java)
+@strong{MySQL} currently has 4 JDBC drivers:
+@itemize @bullet
+@item
+The gwe driver: A Java interface by GWE technologies (not supported anymore).
+@item
+The jms driver: An improved gwe driver by Xiaokun Kelvin ZHU
+@email{X.Zhu@@brad.ac.uk}.
+@item
+The twz driver: A type 4 JDBC driver by Terrence W. Zellers
+@email{zellert@@voicenet.com}. This is commercial but is free for private
+and educational use.
+@item
+The mm driver: A type 4 JDBC driver by Mark Matthews
+@email{mmatthew@@ecn.purdue.edu}. This is released under the GPL.
+@end itemize
+
+The recommended drivers are the twz or mm driver. Both are reported to work
+excellently.
+
+We know that @code{mSQL} has a JDBC driver, but we have too little experience
+with it to compare.
+
+@item Rate of development
+@strong{MySQL} has a very small team of developers, but we are quite
+used to coding C and C++ very rapidly. Because threads, functions,
+@code{GROUP BY} and so on are still not implemented in @code{mSQL}, it
+has a lot of catching up to do. To get some perspective on this, you
+can view the @code{mSQL} @file{HISTORY} file for the last year and
+compare it with the News section of the @strong{MySQL} Reference Manual
+(@pxref{News}). It should be pretty obvious which one has developed
+most rapidly.
+
+@item Utility programs
+Both @code{mSQL} and @strong{MySQL} have many interesting third-party
+tools. Because it is very easy to port upward (from @code{mSQL} to
+@strong{MySQL}), almost all the interesting applications that are available for
+@code{mSQL} are also available for @strong{MySQL}.
+
+@strong{MySQL} comes with a simple @code{msql2mysql} program that fixes
+differences in spelling between @code{mSQL} and @strong{MySQL} for the
+most-used C API functions.
+For example, it changes instances of @code{msqlConnect()} to
+@code{mysql_connect()}. Converting a client program from @code{mSQL} to
+@strong{MySQL} usually takes a couple of minutes.
+@end table
+
+@menu
+* Using mSQL tools:: How to convert @code{mSQL} tools for @strong{MySQL}
+* Protocol differences:: How @code{mSQL} and @strong{MySQL} client/server communications protocols differ
+* Syntax differences:: How @code{mSQL} 2.0 SQL syntax differs from @strong{MySQL}
+@end menu
+
+@node Using mSQL tools, Protocol differences, Compare mSQL, Compare mSQL
+@subsection How to convert @code{mSQL} tools for MySQL
+
+According to our experience, it would just take a few hours to convert tools
+such as @code{msql-tcl} and @code{msqljava} that use the
+@code{mSQL} C API so that they work with the @strong{MySQL} C API.
+
+The conversion procedure is:
+
+@enumerate
+@item
+Run the shell script @code{msql2mysql} on the source. This requires the
+@code{replace} program, which is distributed with @strong{MySQL}.
+@item
+Compile.
+@item
+Fix all compiler errors.
+@end enumerate
+
+Differences between the @code{mSQL} C API and the @strong{MySQL} C API are:
+@itemize @bullet
+@item
+@strong{MySQL} uses a @code{MYSQL} structure as a connection type (@code{mSQL}
+uses an @code{int}).
+@item
+@code{mysql_connect()} takes a pointer to a @code{MYSQL} structure as a
+parameter. It is easy to define one globally or to use @code{malloc()} to get
+one.
+@code{mysql_connect()} also takes two parameters for specifying the user and
+password. You may set these to @code{NULL, NULL} for default use.
+@item
+@code{mysql_error()} takes the @code{MYSQL} structure as a parameter. Just add
+the parameter to your old @code{msql_error()} code if you are porting old code.
+@item
+@strong{MySQL} returns an error number and a text error message for all
+errors. @code{mSQL} returns only a text error message.
+@item
+Some incompatibilities exist as a result of @strong{MySQL} supporting
+multiple connections to the server from the same process.
+@end itemize
+
+@node Protocol differences, Syntax differences, Using mSQL tools, Compare mSQL
+@subsection How @code{mSQL} and MySQL client/server communications protocols differ
+
+There are enough differences that it is impossible (or at least not easy)
+to support both.
+
+The most significant ways in which the @strong{MySQL} protocol differs
+from the @code{mSQL} protocol are listed below:
+
+@itemize @bullet
+@item
+A message buffer may contain many result rows.
+@item
+The message buffers are dynamically enlarged if the query or the
+result is bigger than the current buffer, up to a configurable server and
+client limit.
+@item
+All packets are numbered to catch duplicated or missing packets.
+@item
+All column values are sent in ASCII. The lengths of columns and rows are sent
+in packed binary coding (1, 2 or 3 bytes).
+@item
+@strong{MySQL} can read in the result unbuffered (without having to store the
+full set in the client).
+@item
+If a single read/write takes more than 30 seconds, the server closes
+the connection.
+@item
+If a connection is idle for 8 hours, the server closes the connection.
+@end itemize
+
+@node Syntax differences, , Protocol differences, Compare mSQL
+@subsection How @code{mSQL} 2.0 SQL syntax differs from MySQL
+
+@noindent
+@strong{Column types}
+
+@table @code
+@item @strong{MySQL}
+Has the following additional types (among others; see
+@pxref{CREATE TABLE, , @code{CREATE TABLE}}):
+@itemize @bullet
+@item
+@code{ENUM} type for one of a set of strings.
+@item
+@code{SET} type for many of a set of strings.
+@item
+@code{BIGINT} type for 64-bit integers.
+@end itemize
+@item
+@strong{MySQL} also supports
+the following additional type attributes:
+@itemize @bullet
+@item
+@code{UNSIGNED} option for integer columns.
+@item
+@code{ZEROFILL} option for integer columns.
+@item
+@code{AUTO_INCREMENT} option for integer columns that are a
+@code{PRIMARY KEY}.
+@xref{mysql_insert_id, , @code{mysql_insert_id()}}.
+@item
+@code{DEFAULT} value for all columns.
+@end itemize
+@item mSQL2
+@code{mSQL} column types correspond to the @strong{MySQL} types shown below:
+@multitable @columnfractions .15 .85
+@item @code{mSQL} @strong{type} @tab @strong{Corresponding @strong{MySQL} type}
+@item @code{CHAR(len)} @tab @code{CHAR(len)}
+@item @code{TEXT(len)} @tab @code{TEXT(len)}. @code{len} is the maximal length.
+And @code{LIKE} works.
+@item @code{INT} @tab @code{INT}. With many more options!
+@item @code{REAL} @tab @code{REAL}. Or @code{FLOAT}. Both 4- and 8-byte versions are available.
+@item @code{UINT} @tab @code{INT UNSIGNED}
+@item @code{DATE} @tab @code{DATE}. Uses ANSI SQL format rather than @code{mSQL}'s own format.
+@item @code{TIME} @tab @code{TIME}
+@item @code{MONEY} @tab @code{DECIMAL(12,2)}. A fixed-point value with two decimals.
+@end multitable
+@end table
+
+@noindent
+@strong{Index creation}
+
+@table @code
+@item @strong{MySQL}
+Indexes may be specified at table creation time with the @code{CREATE TABLE}
+statement.
+@item mSQL
+Indexes must be created after the table has been created, with separate
+@code{CREATE INDEX} statements.
+@end table
+
+@noindent
+@strong{To insert a unique identifier into a table}
+
+@table @code
+@item @strong{MySQL}
+Use @code{AUTO_INCREMENT} as a column type
+specifier.
+@xref{mysql_insert_id, , @code{mysql_insert_id()}}.
+@item mSQL
+Create a @code{SEQUENCE} on a table and select the @code{_seq} column.
+@end table
+
+@noindent
+@strong{To obtain a unique identifier for a row}
+
+@table @code
+@item @strong{MySQL}
+Add a @code{PRIMARY KEY} or @code{UNIQUE} key to the table and use this.
+New in 3.23.11: If the @code{PRIMARY} or @code{UNIQUE} key consists of only one
+column and this is of type integer, one can also refer to it as
+@code{_rowid}.
+@item mSQL
+Use the @code{_rowid} column. Observe that @code{_rowid} may change over time
+depending on many factors.
+@end table
+
+@noindent
+@strong{To get the time a column was last modified}
+
+@table @code
+@item @strong{MySQL}
+Add a @code{TIMESTAMP} column to the table. This column is automatically set
+to the current date and time for @code{INSERT} or @code{UPDATE} statements if
+you don't give the column a value or if you give it a @code{NULL} value.
+
+@item mSQL
+Use the @code{_timestamp} column.
+@end table
+
+@noindent
+@strong{@code{NULL} value comparisons}
+
+@table @code
+@item @strong{MySQL}
+@strong{MySQL} follows
+ANSI SQL and a comparison with @code{NULL} is always @code{NULL}.
+@item mSQL
+In @code{mSQL}, @code{NULL = NULL} is TRUE. You
+must change @code{=NULL} to @code{IS NULL} and @code{<>NULL} to
+@code{IS NOT NULL} when porting old code from @code{mSQL} to @strong{MySQL}.
+@end table
+
+@noindent
+@strong{String comparisons}
+
+@table @code
+@item @strong{MySQL}
+Normally, string comparisons are performed in case-independent fashion with
+the sort order determined by the current character set (ISO-8859-1 Latin1 by
+default). If you don't like this, declare your columns with the
+@code{BINARY} attribute, which causes comparisons to be done according to the
+ASCII order used on the @strong{MySQL} server host.
+@item mSQL
+All string comparisons are performed in case-sensitive fashion with
+sorting in ASCII order.
+@end table
+
+@noindent
+@strong{Case-insensitive searching}
+
+@table @code
+@item @strong{MySQL}
+@code{LIKE} is a case-insensitive or case-sensitive operator, depending on
+the columns involved. If possible, @strong{MySQL} uses indexes if the
+@code{LIKE} argument doesn't start with a wildcard character.
+@item mSQL
+Use @code{CLIKE}.
+@end table
+
+@noindent
+@strong{Handling of trailing spaces}
+
+@table @code
+@item @strong{MySQL}
+Strips all spaces at the end of @code{CHAR} and @code{VARCHAR}
+columns. Use a @code{TEXT} column if this behavior is not desired.
+@item mSQL
+Retains trailing space.
+@end table
+
+@noindent
+@strong{@code{WHERE} clauses}
+
+@table @code
+@item @strong{MySQL}
+@strong{MySQL} correctly prioritizes everything (@code{AND} is evaluated
+before @code{OR}). To get @code{mSQL} behavior in @strong{MySQL}, use
+parentheses (as shown below).
+@item mSQL
+Evaluates everything from left to right. This means that some logical
+calculations with more than three arguments cannot be expressed in any
+way. It also means you must change some queries when you upgrade to
+@strong{MySQL}. You do this easily by adding parentheses. Suppose you
+have the following @code{mSQL} query:
+@example
+mysql> SELECT * FROM table WHERE a=1 AND b=2 OR a=3 AND b=4;
+@end example
+To make @strong{MySQL} evaluate this the way that @code{mSQL} would,
+you must add parentheses:
+@example
+mysql> SELECT * FROM table WHERE (a=1 AND (b=2 OR (a=3 AND (b=4))));
+@end example
+@end table
+
+@noindent
+@strong{Access control}
+
+@table @code
+@item @strong{MySQL}
+Has tables to store grant (permission) options per user, host and
+database. @xref{Privileges}.
+@item mSQL
+Has a file @file{mSQL.acl} in which you can grant read/write privileges for
+users.
+@item
+@end table
+
+@node Compare PostgreSQL, , Compare mSQL, Comparisons
+@section How MySQL compares to PostgreSQL
+
+We would first like to note that @code{PostgreSQL} and @strong{MySQL}
+are both widely used products but their design goals are completely
+different. This means that for some applications @strong{MySQL} is more
+suitable and for others @code{PostgreSQL} is more suitable. When
+choosing which database to use you should first check if the databases
+feature set is good enough to satisfy your application. If you need
+speed then @strong{MySQL} is probably your best choice, if you need some
+of the extra features that @code{PostgreSQL} can offer you should use
+@code{PostgreSQL}.
+
+@code{PostgreSQL} has some more advanced features like user-defined
+types, triggers, rules and some transaction support (currently it's
+has about same symantic as @code{MySQL}'s transactions in that the
+transaction is not 100 % atomic) . However, PostgreSQL lacks
+many of the standard types and functions from ANSI SQL and ODBC. See the
+@uref{http://www.mysql.com/information/crash-me.php, @code{crash-me} web page}
+for a complete list of limits and which types and functions are supported
+or unsupported.
+
+Normally, @code{PostgreSQL} is a magnitude slower than
+@strong{MySQL}. @xref{Benchmarks}. This is due largely to they have only
+transaction safe tables and that their transactions system is not as
+sophisticated as Berkeley DB's. In @strong{MySQL} you can decide per
+table if you want the table to be fast or take the speed penalty of
+making it transaction safe.
+
+The most important things that @code{PostgreSQL} supports that @strong{MySQL}
+don't yet support:
+
+@table @code
+@item Sub select
+@item Foregin keys
+@item Stored procedures
+@item An extendable type system.
+@item A way to extend the SQL to handle new key types (like R-trees)
+@end table
+
+@strong{MySQL} on the other hand supports a many ANSI SQL constructs
+that @code{PostgreSQL} doesn't support; Most of these can be found at the
+@uref{http://www.mysql.com/information/crash-me.php, @code{crash-me} web page}.
+
+If you really need the rich type system @code{PostgreSQL} offers and you
+can afford the speed penalty of having to do everything transaction
+safe, you should take a look at @code{PostgreSQL}.
+
+@node MySQL internals, Environment variables, Comparisons, Top
+@chapter MySQL internals
+
+This chapter describes a lot of things that you need to know when
+working on the @strong{MySQL} code.
+
+@menu
+* MySQL threads:: MySQL threads
+@end menu
+
+@node MySQL threads, , MySQL internals, MySQL internals
+@section MySQL threads
+
+The @strong{MySQL} server creates the the following threads:
+
+@itemize @bullet
+@item
+The TCP/IP connection thread handles all connect requests and
+creates a new dedicated thread to handle the authentication and
+and SQL query processing for the connection.
+@item
+On NT there is a named pipe handler thread that does the same work as
+the TCP/IP connection thread on named pipe connect requests.
+@item
+The signal thread handles all signals. This thread also normally handles
+alarms and calls @code{process_alarm()} to force timeouts on connections
+that have been idle too long.
+@item
+If compiled with @code{-DUSE_ALARM_THREAD}, a dedicated thread that
+handles alarms is created. This is only used on some systems where
+there are some problems with @code{sigwait()} or if one wants to use the
+@code{thr_alarm()} code in ones application without a dedicated signal
+handling thread.
+@item
+If one uses the @code{--flush_time=#} option, a dedicated thread is created
+to flush all tables at the given interval.
+@item
+Every connection has its own thread.
+@item
+Every different table on which one uses @code{INSERT DELAYED} gets its
+own thread.
+@item
+If you use @code{--master-host} , slave replication thread will be
+started to read and apply updates from the master.
+@end itemize
+
+@code{mysqladmin processlist} only shows the connection and @code{INSERT
+DELAYED} threads.
+
+
+@page
+@node Environment variables, Users, MySQL internals, Top
+@appendix Environment variables
+
+Here follows a list of all environment variables that are used directly or
+indirectly by @strong{MySQL}. Most of these can also be found at other
+places in this manual.
+
+Note that any options on the command line will take precedence over
+values specified in configuration files and environment variables, and
+values in configuration files take precedence over values in environment
+variables.
+
+In many cases its preferable to use a configure file instead of environment
+variables to modify the behaviour of @strong{MySQL}. @xref{Option files}.
+
+@tindex CCX environment variable
+@tindex Environment variable, CCX
+@tindex CC environment variable
+@tindex Environment variable, CC
+@tindex CFLAGS environment variable
+@tindex Environment variable, CFLAGS
+@tindex CXXFLAGS environment variable
+@tindex Environment variable, CXXFLAGS
+@tindex DBI_USER environment variable
+@tindex Environment variable, DBI_USER
+@tindex DBI_TRACE environment variable
+@tindex Environment variable, DBI_TRACE
+@tindex HOME environment variable
+@tindex Environment variable, HOME
+@tindex LD_RUN_PATH environment variable
+@tindex Environment variable, LD_RUN_PATH
+@tindex MYSQL_DEBUG environment variable
+@tindex Environment variable, MYSQL_DEBUG
+@tindex MYSQL_HISTFILE environment variable
+@tindex Environment variable, MYSQL_HISTFILE
+@tindex MYSQL_HOST environment variable
+@tindex Environment variable, MYSQL_HOST
+@tindex MYSQL_PWD environment variable
+@tindex Environment variable, MYSQL_PWD
+@tindex MYSQL_TCP_PORT environment variable
+@tindex Environment variable, MYSQL_TCP_PORT
+@tindex MYSQL_UNIX_PORT environment variable
+@tindex Environment variable, MYSQL_UNIX_PORT
+@tindex PATH environment variable
+@tindex Environment variable, PATH
+@tindex TMPDIR environment variable
+@tindex Environment variable, TMPDIR
+@tindex TZ environment variable
+@tindex Environment variable, TZ
+@tindex UMASK_DIR environment variable
+@tindex Environment variable, UMASK_DIR
+@tindex UMASK environment variable
+@tindex Environment variable, UMASK
+@tindex USER environment variable
+@tindex Environment variable, USER
+
+@multitable @columnfractions .2 .8
+@item @code{CCX} @tab Set this to your C++ compiler when running configure.
+@item @code{CC} @tab Set this to your C compiler when running configure.
+@item @code{CFLAGS} @tab Flags for your C compiler when running configure.
+@item @code{CXXFLAGS} @tab Flags for your C++ compiler when running configure.
+@item @code{DBI_USER} @tab The default user name for Perl DBI.
+@item @code{DBI_TRACE} @tab Used when tracing Perl DBI.
+@item @code{HOME} @tab The default path for the @code{mysql} history file is @file{$HOME/.mysql_history}.
+@item @code{LD_RUN_PATH} @tab Used to specify where your @code{libmysqlclient.so} is.
+@item @code{MYSQL_DEBUG} @tab Debug-trace options when debugging
+@item @code{MYSQL_HISTFILE} @tab The path to the @code{mysql} history file.
+@item @code{MYSQL_HOST} @tab Default host name used by the @code{mysql} command line prompt.
+@item @code{MYSQL_PWD} @tab The default password when connecting to mysqld. Note that use of this is insecure!
+@item @code{MYSQL_TCP_PORT} @tab The default TCP/IP port.
+@item @code{MYSQL_UNIX_PORT} @tab The default socket; used for connections to @code{localhost}.
+@item @code{PATH} @tab Used by the shell to finds the @strong{MySQL} programs.
+@item @code{TMPDIR} @tab The directory where temporary tables/files are created.
+@item @code{TZ} @tab This should be set to your local timezone. @xref{Timezone problems}.
+@item @code{UMASK_DIR} @tab The user-directory creation mask when creating directories. Note that this is ANDed with @code{UMASK}!
+@item @code{UMASK} @tab The user-file creation mask when creating files.
+@item @code{USER} @tab The default user on Windows to use when connecting to @code{mysqld}.
+@end multitable
+
+@page
+@node Users, Contrib, Environment variables, Top
+@appendix Some MySQL users
+
+@appendixsec General news sites
+
+@itemize @bullet
+
+@item @uref{http://www.yahoo.com/, Yahoo!}
+
+@item @uref{http://slashdot.org/, Slashdot: A pro-Linux/tech news and comment/discussion site}
+
+@item @uref{http://www.linux.com/, All about Linux}
+
+@item @uref{http://www.linuxtoday.com/, Linuxtoday}
+
+@item @uref{http://www.32bitsonline.com/, 32Bits Online: because there's
+more than one way to compute}
+
+@item @uref{http://www.freshmeat.net/, Freshmeat: News about new versions of computer related stuff}
+
+@end itemize
+
+@appendixsec Some Web search engines
+
+@itemize @bullet
+
+@item @uref{http://www.aaa.com.au, AAA Matilda Web Search}
+
+@item @uref{http://www.whatsnu.com/, What's New}
+
+@item @uref{http://www.aladin.de/, Aladin}
+
+@item @uref{http://www.columbus-finder.de/, Columbus Finder}
+
+@item @uref{http://www.spider.de/, Spider}
+
+@item @uref{http://www.blitzsuche.de/, Blitzsuche}
+
+@item @uref{http://www.indoseek.co.id, Indoseek Indonesia}
+
+@item @uref{http://www.yaboo.dk/, Yaboo - Yet Another BOOkmarker}
+
+@c Didn't answer 2000-07-11
+@c @item @uref{http://www.yahoosuck.com, Yahoosuck}
+
+@item @uref{http://www.ozsearch.com.au, OzSearch Internet Guide}
+
+@item @uref{http://www.splatsearch.com/, Splat! Search}
+
+@item @uref{http://osdls.library.arizona.edu/, The Open Source Digital Library System Project}
+@end itemize
+
+@appendixsec Some Information search engines concentrated on some area
+
+@itemize @bullet
+
+@item @uref{http://www.tucows.com/, TuCows Network; Free Software archive}
+
+@item @uref{http://www.jobvertise.com,Jobvertise: Post and search for jobs}
+
+@item @uref{http://www.musicdatabase.com, The Music Database}
+
+@item @uref{http://www.soccersearch.com, Fotball (Soccer) search page}
+
+@item @uref{http://www.headrush.net/takedown, TAKEDOWN - wrestling}
+
+@item @uref{http://www.lyrics.net, The International Lyrics Network}
+
+@item @uref{http://TheMatrix.com/~matrix/band_search.phtml, Musicians looking for other musicians (Free Service)}
+
+@item @uref{http://www.addall.com/AddBooks/Stores.html,AddALL books searching and price comparison}
+
+@item @uref{http://www.herbaria.harvard.edu/Data/Gray/gray.html,Harvard's Gray Herbarium Index of Plant Names}
+
+@item @uref{http://www.game-developer.com/,The Game Development Search Engine}
+
+@item @uref{http://www.i-run.com/html/cookbook.html,My-Recipe.com; Cookbook at i-run.com}
+
+@item @uref{www.theinnkeeper.com, The Innkeeper Vacation Guides}
+
+@item @uref{http://www.macgamedatabase.com/, The Mac Game Database uses PHP and MySQL}
+@c From: Marc Antony Vose <suzerain@suzerain.com>
+
+@item @uref{http://www.csse.monash.edu.au/publications/, Research
+Publications at Monash University in Australia}
+
+@item @uref{http://www.ipielle.emr.it/bts/index.html,
+Occupational Health & Safety website databse (a project for the ECC)}
+@c c.presutti@ipielle.emr.it
+
+@item @uref{http://data.mch.mcgill.ca/, Bioinformatics databases at the
+Montreal Children's Hospital using MySQL}
+@c saeed@www.debelle.mcgill.ca
+@end itemize
+
+@appendixsec Online magazines
+
+@itemize @bullet
+@item @uref{http://www.spoiler.com, Spoiler Webzine}.
+An online magazine featuring music, literature, arts, and design content.
+@item @uref{http://www.linux-magazin.de/newsflash/, Daily news about Linux in German language}
+@item @uref{http://www.betazine.com,Betazine - The Ultimate Online Beta Tester's Magazine}
+@item @uref{http://www.currents.net/ccinfo/aboutcc.html,Computer Currents Magazine}
+@end itemize
+
+@appendixsec Web sites that use MySQL as a backend
+
+@itemize @bullet
+
+@item @uref{http://lindev.jmc.tju.edu/qwor, Qt Widget and Object Repository}
+
+@item @uref{http://www.samba-choro.com.br, Brazilian samba site (in Portuguese)}
+
+@item @uref{http://pgss.iss.uw.edu.pl/en_index.ISS, Polish General Social Survey}
+
+@item @uref{http://www.expo2000.com, Expo2000} World-wide distribution of
+tickets for this event is implemented using @strong{MySQL} and tcl/tk. More than
+5000 travel-agencies all over the world have access to it.
+
+@item @uref{http://www.freevote.com/, FreeVote.com is a free voting
+service with millions of users.}
+
+@item @uref{http://f1.tauzero.se, Forza Motorsport}
+@end itemize
+
+@appendixsec Some Domain/Internet/Web and related services
+
+@itemize @bullet
+
+@item @uref{http://www.wix.com/mysql-hosting, Registry of Web providers that
+support @strong{MySQL}}
+
+@item @uref{http://www.yi.org/, Dynamic DNS Services}
+
+@item @uref{http://www.dynodns.net/, Dynamic domain name service}
+
+@item @uref{http://www.ods.org/, Open DNS Project; free dynamic DNS service}
+
+@c @item @uref{http://dynodns.net, Free dynamic DNS implementation}
+@c EMAIL: A Moore <amoore@mooresystems.com>
+
+@item @uref{http://www.fdns.net/, Free 3rd level domains}
+
+@item @uref{http://worldcommunity.com/, Online Database}
+
+@item @uref{http://www.bigbiz.com, BigBiz Internet Services}
+
+@item @uref{http://virt.circle.net, The Virt Gazette}
+
+@item @uref{http://www.california.com, Global InfoNet Inc}
+
+@item @uref{http://www.webhosters.com, WebHosters - A Guide to WWW Providers}
+
+@item @uref{http://online.dn.ru, Internet information server}
+
+@item @uref{http://www.stopbit.com, A technology news site}
+
+@item @uref{http://www.worldnetla.net, WorldNet Communications - An Internet Services Provider}
+
+@item @uref{http://www.netizen.com.au/, Netizen: Australian-based web consultancy}
+
+@item @uref{http://www.trainingpages.co.uk, Search site for training courses in the UK}
+
+@item @uref{http://chat.nitco.com, Gannon Chat (GPL). Written in Perl and Javascript}
+
+@item @uref{http://www.addurls.com/,A general links directory}
+
+@item @uref{http://www.bookmarktracker.com, A web-based bookmark management service}
+
+@item @uref{http://www.cdrom.com,Walnut Creek CDROM}
+
+@item @uref{http://www.wwwthreads.org/, WWWThreads; Interactive discussion Forums}
+
+@item @uref{http://pvmon.portici.enea.it/Meteo, In Italian; Storage data from meteo station}
+
+@item @uref{http://www.buysell.net/, Online "Person To Person" Auction}
+
+@item @uref{http://tips.pair.com,Tips on web development}
+
+@item @uref{http://www.mailfriends.com, Mailfriends.com is a FREE service for
+everybody who wants to find friends over the internet.}
+
+@item @uref{http://www.uninova.com/cgi-bin/wctelnets?list, Web Page Telnet BBS List}
+
+@item @uref{http://www.uninova.com/cnc.html,UniNova Digital Postcards}
+
+@c @item @uref{http://cabinboy.powersurfr.com, An Internet RFC search engine}
+
+@item @uref{http://www.dslreports.com, DSL providers search with reviews}
+Made with @strong{MySQL} and Modperl, all pages are generated dynamically out of
+the @strong{MySQL} database
+@end itemize
+
+@appendixsec Web sites that use @code{PHP} and MySQL
+
+@itemize @bullet
+@c @item @uref{http://www.wh200th.com, White House 200th Anniversary site}
+
+@item @uref{http://war.jgaa.com:8080/support/index.php3, Jgaa's Internet - Official Support Site}
+
+@item @uref{http://io.incluso.com, Ionline - online publication:} @strong{MySQL},
+PHP, Java, Web programming, DB development
+
+@item @uref{http://www.baboo.com, BaBoo(Browse and bookmark). Free web-based bookmark manager and Calendar}
+
+@item @uref{http://www.courses.pjc.cc.fl.us/Schedule/index.php, Course
+Schedule System at Pensacola Junior College}
+
+@item @uref{http://www.fccj.org, Florida Community College at Jacksonville}
+
+@item @uref{http://www.32bit.com/, 32bit.com; An extensive shareware / freeware archive}
+
+@item @uref{http://www.jokes2000.com/, Jokes 2000}
+@c Added 990604; EMAIL: ah@dybdahl.dk
+
+
+@item @uref{http://www.burken.nu/ , Burken.NU} Burken is a webhotel that
+provides scripts, among other things, for remote users, like counters,
+guestbooks etc.
+@c Added 990608; EMAIL: spacedmp@SpaceDump.Burken.NU (Anders Olausson)
+
+@item @uref{http://tips.pair.com, tips.pair.com} Contains tips on html,
+javascript, 2d/3d graphics and PHP3/MySQL. All pages are generated from
+a database.
+@c Added 990614; EMAIL: downey@image.dk (Rune Madsen)
+
+@end itemize
+
+@appendixsec Some MySQL consultants
+
+@itemize @bullet
+
+@item @uref{http://www.ayni.com, Ayni AG}
+
+@item @uref{http://worldcommunity.com/, Online Database}
+
+@item @uref{http://www2.dataguard.no/,DataGuard (Uses @strong{MySQL} and PHP)}
+
+@item @uref{http://wwits.net/programs/mysql.phtml, WWITS (Uses @strong{MySQL} and PHP)}
+
+@item @uref{http://www.worldcommunity.com/, WCN - The World Community Network}
+
+@item @uref{http://www.chipcastle.com, Chip Castle Dot Com Inc}
+@c Added 990603 EMAIL: chip@chipcastle.com (Chip Castle)
+
+@item @uref{http://www.cyber.com.au/, Cybersource Pty. Ltd}
+
+@item @uref{http://www.spring.de, Spring infotainment gmbh & co. kg}
+@c added 990905 "Oliver Pischke" <opischke@spring.de>
+
+@item @uref{http://www.wamdesign.com/, Develops websites using MySQL}
+@c Added 990905; max@wamdesign.com
+
+@item @uref{http://www.berkeleyconsultants.com, Berkeley Consultants Group}
+
+@end itemize
+
+@appendixsec Programming
+
+@itemize @bullet
+@item @uref{http://www.perl.org/cpan-testers, The Perl CPAN Testers results page}
+@end itemize
+
+
+@appendixsec Uncategorized pages
+
+@itemize @bullet
+
+@item @uref{http://www.feature-showcase.com/htmls/demo_mysql.sql,
+AZC.COM's Feature Showcase}
+
+@item @uref{http://www.teach.org.uk/subjects/trainingcourse/g.html, Course Search}
+
+@item @uref{http://www.northerbys.com, Northerbys Online Auctions}
+
+@item @uref{http://www.schiphol.nl/flights/home.htm, Amsterdam Airport Schiphol}
+
+@item @uref{http://TheMatrix.com/seventhsin/query.phtml, CD database}
+
+@item @uref{http://TheMatrix.com/~flmm/GEAR.html, Used Audio Gear Database}
+
+@item @uref{http://www.kiss.de/musik-mueller, Musical note-sheets}
+
+@item @uref{http://www.bagism.com, Bagism - A John Lennon fan page}
+
+@item @uref{http://www.selftaught.com/, US Folk art broker}
+
+@item @uref{http://organizer.net/, Mail reading on the web}
+
+@item @uref{http://www.mypage.org/, Free home pages on www.somecoolname.mypage.org}
+
+@item @uref{http://www.schulweb.de/, Der Server f@"ur Schulen im Web (In German)}
+
+@item @uref{http://www.ald.net/, Auldhaefen Online Services}
+
+@item @uref{http://www.cary.net/, CaryNET Information Center}
+
+@item @uref{http://www.dataden.com/, Dataden Computer Systems}
+
+@item @uref{http://andree.grm.se/, Andr@'emuseet (In Swedish)}
+
+@item @uref{http://www.him.net/, HOMESITE Internet Marketing}
+
+@item @uref{http://www.jade-v.com/techinfo.html, Jade-V Network Services }
+
+@item @uref{http://ww2010.atmos.uiuc.edu/(Gl)/abt/aknw/tech.rxml,
+Weather World 2010 Technical Credits} @*
+
+@item @uref{http://gimp.foebud.org/registry/doc/, About The Gimp plugin registry}
+
+@item @uref{http://www.fast-inc.com/Products/Archiver/database.html, Java tool
+Archiver technical detail (Slightly optimistic about @strong{MySQL}
+ANSI-92 compliance)}
+
+@item @uref{http://www.gamesdomain.com/cheats/usrcheat.phtml, Games Domain Cheats Database}
+
+@item @uref{http://www.kcilink.com/poweredby/, The "Powered By" Page (Kcilink)}
+
+@item @uref{http://www.netcasting.net/index.whtml, Netcasting}
+
+@item @uref{http://homepages.tig.com.au/~mjj/nbltips, NBL (Australian National Basketball League) tipping}
+
+@item @uref{http://www.cgishop.com/, CGI shop}
+
+@item @uref{http://www.whirlycott.com/, Whirlycott: Website Design}
+
+@item @uref{http://www.mtp.dk, Museum Tusculanum Press}
+
+@item @uref{http://csdgi.historie.ku.dk/biblio, Centro Siciliano di Documentazione}
+
+@item @uref{http://caribou.dyn.ml.org:8000, Quake statistics database}
+
+@item @uref{http://www.astroforum.ch, Astroforum: Astrologie and related things (in German)}
+
+@item @uref{http://www.opendebate.com, OpenDebate - Interactive Polls & Open Discussion}
+
+@item @uref{http://vermeer.organik.uni-erlangen.de/dissertationen/, Online chemical dissertation server}
+
+@item @uref{http://www.freschinfo.com, FreSch! The Free Scholarship Search Service}
+
+@item @uref{http://www.nada.kth.se/~staffanu/pinball, Stockholm Pinball Locator}
+
+@item @uref{http://www.hek.com, HEK A construction company}
+
+@item @uref{http://www.nbi.nl, Elsevier Bussines Information}
+
+@item @uref{http://vaccination.medicallink.se/, Medical Links (Using ColdFusion and @strong{MySQL})}
+
+@item @uref{http://www.joblink-usa.com, Search for jobs & people at JobLink-USA}
+
+@item @uref{http://www.skydive.net/competfs, Competition Formation Skydiving}
+
+@item @uref{http://www.galaxy-net.net/Galaxy-NET Telecommunications, E-commerce and internal accounting}
+
+@item @uref{http://www.borsen.dk/, Denmark's leading business daily newspaper B@o{}rsen}
+
+@item @uref{http://tmmm.simplenet.com/indb/, The Internet NES Database}
+
+@item @uref{http://www.russia.cz, Travel agency in Prague in 3 languages}
+
+@item @uref{http://www.linkstation.de, Linkstation}
+
+@item @uref{http://www.peoplestaff.com, Searchable online database at Peoplestaff}
+
+@item @uref{http://www.dreamhorse.com, A searchable database system for horse classified ads}
+
+@item @uref{http://pootpoot.com/,The Poot site}
+
+@item @uref{http://grateful.net/hw_html/,"Playin' in the LAN"; a network monitoring suite}
+
+@c Update from Christopher Milton <cmilton@bwn.net> 1999-12-21
+@item @uref{http://www.usapa.army.mil,U.S. Army Publishing Agency}
+
+@item @uref{http://www.nekretnine.co.yu/,Realestate handling in Yugoslavia}
+
+@item @uref{http://demo.cpsoft.com/pims/devFAQ.html, PIMS; a Patient Information Management System}
+
+@item @uref{http://cpsoft.com,Pilkington Software Inc}
+
+@item @uref{http://www.no-quarter.org/,A Vietnam Veteran's Memorial (The Wall) database.}
+
+@item @uref{http://www.gamers-union.com/,Gamer's Union specializes inauctions of used & out of print gaming material}
+
+@item @uref{http://www.montereyhigh.com/office/dbul.php3, A daily bulletin at Monterey High school}
+
+@item @uref{http://www.myEastside.com,Community-owned site serving Lake
+Washington's Eastside residents and businesses}
+
+@item @uref{http://bowling-france.net/,French bowling site}.
+@end itemize
+
+Send any additions to this list to @email{webmaster@@mysql.com}.
+
+@page
+@node Contrib, Credits, Users, Top
+@appendix Contributed programs
+
+Many users of @strong{MySQL} have contributed @emph{very} useful support
+tools and addons.
+
+@ifclear web
+A list of what is available at @uref{http://www.mysql.com/Downloads/Contrib/}
+(or any mirror) is shown below.
+If you want to build @strong{MySQL} support for the Perl @code{DBI}/@code{DBD}
+interface, you should fetch the @code{Data-Dumper}, @code{DBI}, and
+@code{Msql-Mysql-modules} files and install them.
+@xref{Perl support}.
+@end ifclear
+
+
+@uref{http://www.mysql.com/Downloads/Contrib/00-README, 00-README}
+This listing.
+
+@appendixsec API's
+
+@itemize @bullet
+@item Perl modules
+@itemize @bullet
+@item @uref{http://www.mysql.com/Downloads/Contrib/Data-Dumper-2.101.tar.gz, Data-Dumper-2.101.tar.gz}
+Perl @code{Data-Dumper} module. Useful with @code{DBI}/@code{DBD} support for
+older perl installations.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/DBI-1.13.tar.gz, DBI-1.13.tar.gz}
+Perl @code{DBI} module.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/KAMXbase1.0.tar.gz,KAMXbase1.0.tar.gz}
+Convert between @file{.dbf} files and @strong{MySQL} tables. Perl
+module written by Pratap Pereira @email{pereira@@ee.eng.ohio-state.edu},
+extened by Kevin A. McGrail @email{kmcgrail@@digital1.peregrinehw.com}.
+This converter can handle MEMO fields.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/Msql-Mysql-modules-1.2214.tar.gz, Msql-Mysql-modules-1.2214.tar.gz}
+Perl @code{DBD} module to access mSQL and @strong{MySQL} databases..
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/Data-ShowTable-3.3.tar.gz, Data-ShowTable-3.3.tar.gz}
+Perl @code{Data-ShowTable} module. Useful with @code{DBI}/@code{DBD} support.
+@end itemize
+
+@item JDBC
+@itemize @bullet
+@item @uref{http://www.mysql.com/Downloads/Contrib/mm.mysql.jdbc-1.2c.tar.gz, mm.mysql.jdbc-1.2c.tar.gz}
+The mm JDBC driver for @strong{MySQL}. This is a production release
+and is actively developed. By Mark Matthews
+(@email{mmatthew@@ecn.purdue.edu}).
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mm.mysql.jdbc-2.0pre5.tar.gz, mm.mysql.jdbc-2.0pre5.tar.gz}
+The mm JDBC driver for @strong{MySQL}. This is a pre-release beta version
+and is actively developed. By Mark Matthews
+(@email{mmatthew@@ecn.purdue.edu}).
+The two drivers above have an LGPL
+license. Please check @uref{http://www.worldserver.com/mm.mysql/} for
+the latest drivers (and other JDBC information) because these drivers may be out of date.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/twz1jdbcForMysql-1.0.4-GA.tar.gz, twz1jdbcForMysql-1.0.4-GA.tar.gz}
+The twz driver: A type 4 JDBC driver by Terrence W. Zellers
+@email{zellert@@voicenet.com}. This is commercial but is free for
+private and educational use.
+@c no answer from server 990830
+@c You can always find the latest driver at @uref{http://www.voicenet.com/~zellert/tjFM/}.
+@item
+@item @uref{http://www.mysql.com/Downloads/Contrib/pmdamysql.tgz,pmdamysql.tgz}
+A @strong{MySQL} PMDA. Provides @strong{MySQL} server status and configuration
+variables.
+@end itemize
+
+@item C++
+@itemize @bullet
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-c++-0.02.tar.gz, mysql-c++-0.02.tar.gz}
+@strong{MySQL} C++ wrapper library. By Roland Haenel,
+@email{rh@@ginster.net}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/MyDAO.tar.gz, MyDAO}
+@strong{MySQL} C++ API. By Satish @email{spitfire@@pn3.vsnl.net.in}. Inspired
+by Roland Haenel's C++ API and Ed Carp's MyC library.
+
+@item @uref{http://www.mysql.com/download_mysql++.html, mysql++}
+@strong{MySQL} C++ API (More than just a wrapper library). Originally by
+@email{kevina@@clark.net}. Nowadays maintained by Sinisa at MySQL AB.
+
+@item @uref{http://nelsonjr.homepage.com/NJrAPI,NJrAPI}
+A C++ database independent library that supports @strong{MySQL}.
+@end itemize
+
+@item Delphi
+@itemize @bullet
+@item @uref{http://www.mysql.com/Downloads/Contrib/delphi-interface.gz, delphi-interface.gz}
+Delphi interface to @code{libmysql.dll}, by Blestan Tabakov,
+@email{root@@tdg.bis.bg}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/DelphiMySQL2.zip, DelphiMySQL2.zip}
+Delphi interface to @code{libmysql.dll}, by @email{bsilva@@umesd.k12.or.us}
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/Udmysel.pas, Udmysql.pas}
+A wrapper for libmysql.dll for usage in Delphi. By Reiner Sombrowsky.
+
+@item @uref{http://www.fichtner.net/delphi/mysql.delphi.phtml, A Delphi interface to @strong{MySQL}.}
+With source code. By Matthias Fichtner.
+
+@item @uref{http://www.productivity.org/projects/mysql/, @strong{TmySQL}
+A library to use @strong{MySQL} with Delphi}
+
+@item @uref{http://www.geocities.com/CapeCanaveral/2064/mysql.html, Delphi TDataset-component}
+@end itemize
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-ruby-2.2.0.tar.gz, mysql-ruby-2.2.0.tar.gz}
+@strong{MySQL} Ruby module. By TOMITA Masahiro @email{tommy@@tmtm.org}
+@uref{http://www.netlab.co.jp/ruby/,Ruby} is an Object-Oriented Interpreter Language.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/JdmMysqlDriver-0.1.0.tar.gz,JdmMysqlDriver-0.1.0.tar.gz}
+A VisualWorks 3.0 Smalltalk driver for @strong{MySQL}. By
+@email{joshmiller@@earthlink.net}
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/Db.py, Db.py}
+Python module with caching. By @email{gandalf@@rosmail.com}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/MySQLmodule-1.4.tar.gz, MySQLmodule-1.4.tar.gz}
+Python interface for @strong{MySQL}. By Joseph Skinner @email{joe@@earthlight.co.nz}; Modified by Joerg Senekowitsch @email{senekow@@ibm.net}
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_mex_1_1.tar.gz, mysql_mex_1_1.tar.gz}
+An interface program for the Matlab program by MathWorks. The interface
+is done by Kimmo Uutela and John Fisher (not by Mathworks).
+Check @uref{http://boojum.hut.fi/~kuutela/mysqlmex.html,mysqlmex.html}
+for more information.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqltcl-1.53.tar.gz, mysqltcl-1.53.tar.gz}
+Tcl interface for @strong{MySQL}. Based on @file{msqltcl-1.50.tar.gz}.
+Updated by Tobias Ritzau, @email{tobri@@ida.liu.se}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/MyC-0.1.tar.gz, MyC-0.1.tar.gz}
+A Visual Basic-like API, by Ed Carp.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/sqlscreens-1.0.1.tar.gz, sqlscreens-1.0.1.tar.gz}
+Tcl/Tk code to generate database screens. By Jean-Francois Dockes.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/Vdb-dflts-2.1.tar.gz, Vdb-dflts-2.1.tar.gz}
+This is a new version of a set of library utilities intended
+to provide a generic interface to SQL database engines such that your
+application becomes a 3-tiered application. The advantage is that you
+can easily switch between and move to other database engines by
+implementing one file for the new backend without needing to make any
+changes to your applications. By @email{damian@@cablenet.net}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/DbFramework-1.10.tar.gz, DbFramework-1.10.tar.gz}
+DbFramework is a collection of classes for manipulating @strong{MySQL}
+databases. The classes are loosely based on the CDIF Data Model
+Subject Area. By Paul Sharpe @email{paul@@miraclefish.com}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/pike-mysql-1.4.tar.gz, pike-mysql-1.4.tar.gz}
+@strong{MySQL} module for pike. For use with the Roxen web server.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/squile.tar.gz, squile.tar.gz}
+Module for @code{guile} that allows @code{guile} to interact with SQL
+databases. By Hal Roberts.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/stk-mysql.tar.gz, stk-mysql.tar.gz}
+Interface for Stk. Stk is the Tk widgets with Scheme underneath instead of Tcl.
+By Terry Jones
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/eiffel-wrapper-1.0.tar.gz,eiffel-wrapper-1.0.tar.gz}.
+Eiffel wrapper by Michael Ravits.
+@end itemize
+
+@appendixsec Clients
+
+@itemize @bullet
+@item Graphical clients
+@itemize @bullet
+@item @uref{http://www.mysql.com/download_clients.html, mysqlgui homepage}
+The @strong{MySQL} GUI client homepage. By Sinisa at MySQL AB.
+@item @uref{http://www.mysql.com/Downloads/Contrib/kmysqladmin-0.4.1.tar.gz, kmysqladmin-0.4.1.tar.gz}
+@item @uref{http://www.mysql.com/Downloads/Contrib/kmysqladmin-0.4.1-1.src.rpm, kmysqladmin-0.4.1-1.src.rpm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/kmysqladmin-0.4.1-1.i386.rpm, kmysqladmin-0.4.1-1.i386.rpm}
+An administration tool for the @strong{MySQL} server using QT / KDE. Tested
+only on Linux.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-admin-using-java+swing.tar.gz, Java client
+using Swing} By Fredy Fischer, @email{se-afs@@dial.eunet.ch}. You can
+always find the latest version
+@uref{http://www.trash.net/~ffischer/admin/index.html, here}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqlwinadmn.zip, mysqlwinadmn.zip}
+Win32 GUI (binary only) to administrate a database, by David B. Mansel,
+@email{david@@zhadum.org}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/netadmin.zip, netadmin.zip}
+An administrator tool for @strong{MySQL} on Windows 95/98 and Windows NT
+4.0. Only tested with @strong{MySQL} 3.23.5 - 3.23.7. Written using the
+Tmysql components.
+
+You can write queries and show tables, indexes, table syntax and
+administrate user,host and database and so on. The is still beta and
+have still some bugs. you can test the program with all features. Please
+send bugs and hints to Marco Suess @email{ms@@it-netservice.de}. Original
+URL @url{http://www.it-netservice.de/pages/software/index.html}.
+
+@item @uref{http://www.mysql.com/Downloads/Win32/admin13.exe,Atronic's @strong{MySQL} client for Win32 1.3.0.0} and @uref{http://www.mysql.com/Downloads/Win32/admin13.readme,Atronic's @strong{MySQL} client readme}.
+Home page for this can be found at: @uref{http://www.artronic.hr}.
+@item @uref{http://www.mysql.com/Downloads/Win32/W9xstop.zip,Utility from Artronic to stop MySQL on win9x}
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/xmysqladmin-1.0.tar.gz, xmysqladmin-1.0.tar.gz}
+An X based front end to the @strong{MySQL} database engine. It allows reloads,
+status check, process control, myisamchk, grant/revoke privileges,
+creating databases, dropping databases, create, alter, browse and drop
+tables. Originally by Gilbert Therrien, @email{gilbert@@ican.net} but
+now in public domain and supported by MySQL AB.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/xmysql-1.9.tar.gz, xmysql-1.9.tar.gz}
+@item @uref{http://web.wt.net/~dblhack, xmysql home page}
+A front end to the @strong{MySQL} database engine. It allows for simple
+queries and table maintenance, as well as batch queries. By Rick
+Mehalick, @email{dblhack@@wt.net}.
+Requires @uref{http://bragg.phys.uwm.edu/xforms,xforms 0.88} to work.
+@item @uref{http://www.tamos.net/sw/dbMetrix,dbMetrix}
+An open source client for exploring databases and executing SQL. Supports
+@strong{MySQL}, Oracle, PostgreSQL and mSQL.
+@item @uref{http://www.multimania.com/bbrox/GtkSQL,GtkSQL}
+A query tool for @strong{MySQL} and PostgreSQL.
+@item @uref{http://dbman.linux.cz/,dbMan}
+A query tool written in Perl. Uses DBI and Tk.
+@item @uref{http://www.mysql.com/Downloads/Contrib/mascon1.exe, mascon1.exe}
+You can get the newest one from
+@uref{http://www.SciBit.com,http://www.SciBit.com}.
+@item @uref{http://www.virtualbeer.net/dbui/,DBUI}
+DBUI is a Gtk graphical database editor.
+@end itemize
+
+@item Web clients
+@itemize @bullet
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqladmin-atif-1.0.tar.gz, mysqladmin-atif-1.0.tar.gz}
+WWW @strong{MySQL} administrator for the @code{user,} @code{db} and
+@code{host} tables. By Tim Sailer, modified by Atif Ghaffar
+@email{aghaffar@@artemedia.ch}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-webadmin-1.0a8-rz.tar.gz, mysql-webadmin-1.0a8-rz.tar.gz}
+A tool written in PHP-FI to administrate @strong{MySQL} databases
+remotely over the web within a Web-Browser. By Peter Kuppelwieser,
+@email{peter.kuppelwieser@@kantea.it}. Updated by Wim Bonis,
+@email{bonis@@kiss.de}. Not maintained anymore!
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqladm.tar.gz, mysqladm.tar.gz}
+@strong{MySQL} Web Database Administration written in Perl. By Tim Sailer.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqladm-2.tar.gz, mysqladm-2.tar.gz}
+Updated version of @file{mysqladm.tar.gz}, by High Tide.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/billowmysql.zip, billowmysql.zip}
+Updated version of @file{mysqladm.tar.gz}, by Ying Gao. You can get the
+newest version from @uref{http://civeng.com/sqldemo/, the home site}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/myadmin-0.4.tar.gz, myadmin-0.4.tar.gz}
+@item @uref{http://myadmin.cheapnet.net/, MyAdmin home page}
+A web based mysql administrator by Mike Machado.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/phpMyAdmin_2.0.1.tar.gz,phpMyAdmin_2.0.1.tar.gz}
+A set of PHP3-scripts to adminstrate @strong{MySQL} over the WWW.
+
+@item @uref{http://www.htmlwizard.net/phpMyAdmin/, phpMyAdmin home page}
+A PHP3 tool in the spirit of mysql-webadmin, by Tobias Ratschiller, tobias@@dnet.it
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/useradm.tar.gz, useradm.tar.gz}
+@strong{MySQL} administrator in PHP. By Ofni Thomas
+@email{othomas@@vaidsystems.com}.
+@end itemize
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-editor.tar.gz,mysql-editor.tar.gz}
+This cgi scripts in Perl enables you to edit content of Mysql
+database. By Tomas Zeman.
+@item
+@uref{http://futurerealm.com/opensource/futuresql.htm, FutureSQL Web Database Administration Tool}.
+FutureSQL by Peter F. Brown, is a Free, Open Source Rapid Application
+Development web database administration tool, written in Perl,
+using @strong{MySQL}. It uses @code{DBI:DBD} and @code{CGI.pm}.
+
+FutureSQL allows one to easily setup config files to view, edit, delete
+and otherwise process records from a @strong{MySQL} database. It uses a data
+dictionary, configuration files and templates, and allows "pre-processing"
+and "post-processing" on both fields, records and operations.
+@end itemize
+
+
+@appendixsec Web tools
+
+@itemize @bullet
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mod_mysql_include_1.0.tar.gz, mod_mysql_include_1.0.tar.gz}
+Apache module to include HTML from MySQL queries into your pages, and run update queries.
+Originally written to implement a simple fast low-overhead banner-rotation system.
+By Sasha Pachev.
+
+@item @uref{http://www.odbsoft.com/cook/sources.htm}
+This package has various functions for generating html code from a SQL
+table structure and for generating SQL statements (Select, Insert,
+Update, Delete) from an html form. You can build a complete forms
+interface to a SQL database (query, add, update, delete) without any
+programming! By Marc Beneteau, @email{marc@@odbsoft.com}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/sqlhtml.tar.gz, sqlhtml.tar.gz}
+SQL/HTML is an HTML database manager for @strong{MySQL} using @code{DBI} 1.06.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/udmsearch-2.2.1b.tar.gz, UdmSearch 2.2.1b (stable version)}
+@item @uref{http://www.mysql.com/Downloads/Contrib/udmsearch-3.0.5.tar.gz, UdmSearch 3.0.5 (development version)}
+@item @uref{http://mysearch.udm.net, UdmSearch home page}
+A @strong{MySQL}- and PHP- based search engine over HTTP. By
+Alexander I. Barkov @email{bar@@izhcom.ru}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/wmtcl.doc, wmtcl.doc}
+@item @uref{http://www.mysql.com/Downloads/Contrib/wmtcl.lex, wmtcl.lex}
+With this you can write HTML files with inclusions of Tcl code. By
+@email{vvs@@scil.npi.msu.su}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/www-sql-0.5.7.lsm, www-sql-0.5.7.lsm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/www-sql-0.5.7.tar.gz, www-sql-0.5.7.tar.gz}
+A CGI program that parses an HTML file containing special tags, parses
+them and inserts data from a @strong{MySQL} database.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/genquery.zip, genquery.zip}
+Perl SQL database interface package for html.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/cgi++-0.8.tar.gz, cgi++-0.8.tar.gz}
+A macro-processor to simply writing CGI/Database programs in C++ by Sasha Pachev.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/webboard-1.0.zip, WebBoard 1.0}
+EU-Industries Internet-Message-Board.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/DBIx-TextIndex-0.02.tar.gz, DBIx-TextIndex-0.02.tar.gz}
+Full-text searching with Perl on @code{BLOB}/@code{TEXT} columns by Daniel Koch.
+@end itemize
+
+@appendixsec Performance Benchmarking tools
+
+@itemize @bullet
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-bench-0.6.tar.gz, mysql-super-smack and friends}
+User-customizable multi-threaded tool set to benchmark @strong{MySQL}. By Sasha Pachev.
+@end itemize
+
+@appendixsec Authentication tools
+
+@itemize @bullet
+@item @uref{http://www.mysql.com/Downloads/Contrib/ascend-radius-mysql-0.7.1.patch.gz,
+ascend-radius-mysql-0.7.1.patch.gz}
+This is authentication and logging patch using @strong{MySQL} for
+Ascend-Radius. By @email{takeshi@@SoftAgency.co.jp}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/icradius-0.10.tar.gz, icradius 0.10}
+@uref{http://www.mysql.com/Downloads/Contrib/icradius.README, icradius readme file}
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/checkpassword-0.81-mysql-0.6.5.patch.gz,
+checkpassword-0.81-mysql-0.6.5.patch.gz}
+@strong{MySQL} authentication patch for QMAIL and checkpassword. These are
+useful for management user(mail,pop account) by @strong{MySQL}.
+By @email{takeshi@@SoftAgency.co.jp}
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/jradius-diff.gz, jradius-diff.gz}
+@strong{MySQL} support for Livingston's Radius 2.01. Authentication and
+Accounting. By Jose de Leon, @email{jdl@@thevision.net}
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mod_auth_mysql-2.20.tar.gz, mod_auth_mysql-2.20.tar.gz}
+Apache authentication module for @strong{MySQL}. By Zeev Suraski,
+@email{bourbon@@netvision.net.il}.
+
+@strong{Please} register this module at:
+@url{http://bourbon.netvision.net.il/mysql/mod_auth_mysql/register.html}. The
+registering information is only used for statistical purposes and will
+encourage further development of this module!
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mod_log_mysql-1.05.tar.gz, mod_log_mysql-1.05.tar.gz}
+@strong{MySQL} logging module for Apache. By Zeev Suraski,
+@email{bourbon@@netvision.net.il}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mypasswd-2.0.tar.gz, mypasswd-2.0.tar.gz}
+Extra for @code{mod_auth_mysql}. This is a little tool that allows you
+to add/change user records storing group and/or password entries in
+@strong{MySQL} tables. By Harry Brueckner, @email{brueckner@@respublica.de}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-passwd.README, mysql-passwd.README}
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql-passwd-1.2.tar.gz, mysql-passwd-1.2.tar.gz}
+Extra for @code{mod_auth_mysql}. This is a two-part system for use with
+@code{mod_auth_mysql}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/pam_mysql.tar.gz, pam_mysql.tar.gz}
+This module authenticates users via @code{pam}, using @strong{MySQL}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/nsapi_auth_mysql.tar, nsapi_auth_mysql.tar}
+Netscape Web Server API (NSAPI) functions to authenticate (BASIC) users
+against @strong{MySQL} tables. By Yuan John Jiang.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/qmail-1.03-mysql-0.6.5.patch.gz,
+qmail-1.03-mysql-0.6.5.patch.gz}
+Patch for qmail to authenticate users from a @strong{MySQL} table.
+@item @uref{http://www.mysql.com/Downloads/Contrib/pwcheck_mysql-0.1.tar.gz,pwcheck_mysql-0.1.tar.gz}
+An authentication module for the Cyrus IMAP server. By Aaron Newsome.
+@end itemize
+
+@appendixsec Converters
+
+@itemize @bullet
+@item @uref{http://www.mysql.com/Downloads/Contrib/dbf2mysql-1.14.tgz, dbf2mysql-1.14.tgz}
+Convert between @file{.dbf} files and @strong{MySQL} tables. By Maarten
+Boekhold, @email{boekhold@@cindy.et.tudelft.nl}, William Volkman and
+Michael Widenius. This converter includes rudementary read-only support
+for MEMO fields.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/dbf2mysql-1.13.tgz, dbf2mysql-1.13.tgz}
+Convert between @file{.dbf} files and @strong{MySQL} tables. By Maarten
+Boekhold, @email{boekhold@@cindy.et.tudelft.nl}, and Michael Widenius.
+This converter can't handle MEMO fields.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/dbf2mysql.zip, dbf2mysql.zip}
+Convert between FoxPro @file{.dbf} files and @strong{MySQL} tables on Win32.
+By Alexander Eltsyn, @email{ae@@nica.ru} or @email{ae@@usa.net}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/dump2h-1.20.gz, dump2h-1.20.gz}
+Convert from @code{mysqldump} output to a C header file. By Harry Brueckner,
+@email{brueckner@@mail.respublica.de}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/exportsql.txt, exportsql.txt}
+A script that is similar to @code{access_to_mysql.txt}, except that this
+one is fully configurable, has better type conversion (including
+detection of @code{TIMESTAMP} fields), provides warnings and suggestions
+while converting, quotes @strong{all} special characters in text and
+binary data, and so on. It will also convert to @code{mSQL} v1 and v2,
+and is free of charge for anyone. See
+@uref{http://www.cynergi.net/prod/exportsql/} for latest version. By
+Pedro Freire, @email{support@@cynergi.net}. Note: Doesn't work with
+Access2!
+@item @uref{http://www.mysql.com/Downloads/Contrib/access_to_mysql.txt, access_to_mysql.txt}
+Paste this function into an Access module of a database which has the
+tables you want to export. See also @code{exportsql}. By Brian Andrews.
+Note: Doesn't work with Access2!
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/importsql.txt, importsql.txt}
+A script that does the exact reverse of @code{exportsql.txt}. That is,
+it imports data from @strong{MySQL} into an Access database via
+ODBC. This is very handy when combined with exportsql, because it lets you
+use Access for all DB design and administration, and synchronize with
+your actual @strong{MySQL} server either way. Free of charge. See
+@uref{http://www.netdive.com/freebies/importsql/} for any updates.
+Created by Laurent Bossavit of NetDIVE.
+@strong{Note:} Doesn't work with Access2!
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/msql2mysqlWrapper-1.0.tgz, /msql2mysqlWrapper 1.0}
+A C wrapper from @code{mSQL} to @strong{MySQL}. By @email{alfred@@sb.net}
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/sqlconv.pl, sqlconv.pl}
+A simple script that can be used to copy fields from one @strong{MySQL} table to
+another in bulk. Basically, you can run @code{mysqldump} and pipe it to
+the @code{sqlconv.pl} script and the script will parse through the
+@code{mysqldump} output and will rearrange the fields so they can be
+inserted into a new table. An example is when you want to create a new
+table for a different site you are working on, but the table is just a
+bit different (ie - fields in different order, etc.).
+By Steve Shreeve.
+@end itemize
+
+@appendixsec Using MySQL with other products
+
+@itemize @bullet
+@item @uref{http://www.mysql.com/Downloads/Contrib/emacs-sql-mode.tar.gz, emacs-sql-mode.tar.gz}
+Raw port of a SQL mode for XEmacs. Supports completion. Original by
+Peter D. Pezaris @email{pez@@atlantic2.sbi.com} and partial
+@strong{MySQL} port by David Axmark.
+
+@item @uref{http://www.mysql.com/Downloads/Win32/MyAccess97_Ver_1_01.zip, MyAccess97 1.01}
+MyAccess is an AddIn for Access 97 and handles a lot of maintanance work
+for @strong{MySQL} databases.
+
+@item @uref{http://www.mysql.com/Downloads/Win32/MyAccess2000_Ver_1_01.zip, MyAccess2000 1.01}
+MyAccess is an AddIn for Access 2000 and handles a lot of maintanance work
+for @strong{MySQL} databases.
+
+@uref{http://www.mysql.com/Downloads/Win32/MyAccess-1.01.readme,
+MyAccess-readme}. By Hubertus Hiden.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/radius-0.3.tar.gz, radius-0.3.tar.gz}
+Patches for @code{radiusd} to make it support @strong{MySQL}. By Wim Bonis,
+@email{bonis@@kiss.de}.
+@end itemize
+
+@appendixsec Useful tools
+
+@itemize @bullet
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_watchdog.pl, mysql_watchdog.pl}
+Monitor the @strong{MySQL} daemon for possible lockups. By Yermo Lamers,
+@email{yml@@yml.com}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqltop.tar.gz, mysqltop.tar.gz}
+Sends a query in a fixed time interval to the server and shows the
+resulting table. By Thomas Wana.
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_structure_dumper.tar.gz,mysql_structure_dumper.tar.gz}
+Prints out the structure of the all tables in a database. By Thomas Wana.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_structure_dumper.tgz, structure_dumper.tgz}
+Prints the structure of every table in a database. By Thomas Wana.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysqlsync, mysqlsync-1.0-alpha.tar.gz}.
+A perl script to keep remote copies of a @strong{MySQL} database in sync with a
+central master copy. By Mark Jeftovic. @email{markjr@@easydns.com}
+@item @uref{http://www.mysql.com/Downloads/Contrib/MySQLTutor-0.2.tar.gz, MySQLTutor}.
+MySQLTutor. A tutor of @strong{MySQL} for beginners
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/MySQLDB.zip, MySQLDB.zip}
+A COM library for @strong{MySQL} by Alok Singh.
+@item @uref{http://www.mysql.com/Downloads/Contrib/MySQLDB-readme.html, MySQLDB-readme.html}
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysql_replicate.pl, mysql_replicate.pl}
+Perl program that handles replication. By @email{elble@@icculus.nsg.nwu.edu}
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/DBIx-TextIndex-0.02.tar.gz, DBIx-TextIndex-0.02.tar.gz}
+Perl script that uses reverse indexing to handle text searching.
+By Daniel Koch.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/dbcheck, dbcheck}
+Perl script that takes a backup of a tables before running isamchk on them.
+By Elizabeth.
+@end itemize
+
+@appendixsec RPMs for common tools (Most are for RedHat 6.1)
+
+@itemize @bullet
+@item @uref{http://www.mysql.com/Downloads/Contrib/perl-Data-ShowTable-3.3-2.i386.rpm,perl-Data-ShowTable-3.3-2.i386.rpm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/perl-Msql-Mysql-modules-1.2210-2.i386.rpm,perl-Msql-Mysql-modules-1.2210-2.i386.rpm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/php-pg-3.0.13-1.i386.rpm,php-pg-3.0.13-1.i386.rpm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/php-pg-manual-3.0.13-1.i386.rpm,php-pg-manual-3.0.13-1.i386.rpm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/php-pg-mysql-3.0.13-1.i386.rpm,php-pg-mysql-3.0.13-1.i386.rpm}
+@item @uref{http://www.mysql.com/Downloads/Contrib/phpMyAdmin-2.0.5-1.noarch.rpm,phpMyAdmin-2.0.5-1.noarch.rpm}
+@end itemize
+
+@appendixsec Useful functions
+@itemize @bullet
+@item @uref{http://www.mysql.com/Downloads/Contrib/mysnprintf.c,mysnprintf.c}
+sprintf() function for SQL queries that can escape blobs. By Chunhua Liu.
+@end itemize
+
+@appendixsec Uncategorized
+
+@itemize @bullet
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/findres.pl, findres.pl}
+Find reserved words in tables. By Nem W Schlecht.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/handicap.tar.gz, handicap.tar.gz}
+Performance handicapping system for yachts. Uses PHP. By
+@email{rhill@@stobyn.ml.org}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/hylalog-1.0.tar.gz, hylalog-1.0.tar.gz}
+Store @code{hylafax} outgoing faxes in a @strong{MySQL} database. By Sinisa
+Milivojevic, @email{sinisa@@mysql.com}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/mrtg-mysql-1.0.tar.gz, mrtg-mysql-1.0.tar.gz}
+@strong{MySQL} status plotting with MRTG, by Luuk de Boer, @email{luuk@@wxs.nl}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/wuftpd-2.4.2.18-mysql_support.2.tar.gz, wuftpd-2.4.2.18-mysql_support.2.tar.gz}
+Patches to add logging to @strong{MySQL} for WU-ftpd. By Zeev Suraski,
+@email{bourbon@@netvision.net.il}.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/wu-ftpd-2.6.0-mysql.4.tar.gz,wu-ftpd-2.6.0-mysql.4.tar.gz}
+Patches to add logging to @strong{MySQL} for WU-ftpd 2.6.0. By,
+@email{takeshi@@SoftAgency.co.jp}, based on Zeev Suraski wuftpd patches.
+
+@item @uref{http://www.mysql.com/Downloads/Contrib/Old-Versions, Old-Versions}
+Previous versions of things found here that you probably won't be
+interested in.
+@end itemize
+
+
+@page
+@node Credits, News, Contrib, Top
+@appendix Contributors to MySQL
+
+Contributors to the @strong{MySQL} distribution are listed below, in
+somewhat random order:
+
+@table @asis
+@item Michael (Monty) Widenius
+Has written the following parts of @strong{MySQL}:
+@itemize @bullet
+@item
+All the main code in @code{mysqld}.
+@item
+New functions for the string library.
+@item
+Most of the @code{mysys} library.
+@item
+The @code{ISAM} and @code{MyISAM} libraries (B-tree index file
+handlers with index compression and different record formats).
+@item
+The @code{HEAP} library. A memory table system with our superior full dynamic
+hashing. In use since 1981 and published around 1984.
+@item
+The @code{replace} program (look into it, it's COOL!).
+@item
+@strong{MyODBC}, the ODBC driver for Windows95.
+@item
+Fixing bugs in MIT-pthreads to get it to work for @strong{MySQL}. And
+also Unireg, a curses-based application tool with many utilities.
+@item
+Porting of @code{mSQL} tools like @code{msqlperl}, @code{DBD}/@code{DBI} and
+@code{DB2mysql}.
+@item
+Most parts of crash-me and the @strong{MySQL} benchmarks.
+@end itemize
+@item David Axmark
+@itemize @bullet
+@item
+Coordinator and main writer for the @strong{Reference Manual}, including
+enhancements to @code{texi2html}. Also automatic website updating from
+this manual.
+@item
+Autoconf, Automake and @code{libtool} support.
+@item
+The licensing stuff.
+@item
+Parts of all the text files. (Nowadays only the @file{README} is
+left. The rest ended up in the manual.)
+@item
+Our Mail master.
+@item
+Lots of testing of new features.
+@item
+Our in-house ``free'' software lawyer.
+@item
+Mailing list maintainer (who never has the time to do it right...)
+@item
+Our original portability code (more than 10 years old now). Nowadays
+only some parts of @code{mysys} are left.
+@item
+Someone for Monty to call in the middle of the night when he just got
+that new feature to work. :-)
+@end itemize
+@item Paul DuBois
+Help with making the Reference Manual correct and understandable. That
+includes rewriting Monty's and David's attempts at English into English
+as other people know it.
+@item Gianmassimo Vigazzola @email{qwerg@@mbox.vol.it} or @email{qwerg@@tin.it}
+The initial port to Win32/NT.
+@item Kim Aldale
+Helped to rewrite Monty's and David's early attempts at English into
+English.
+@item Allan Larsson (The BOSS for TCX DataKonsult AB)
+For all the time he has allowed Monty to spend on this ``maybe useful''
+tool (@strong{MySQL}). Dedicated user (and bug finder) of Unireg &
+@strong{MySQL}.
+@item Per Eric Olsson
+For more or less constructive criticism and real testing of the dynamic
+record format.
+@item Irena Pancirov @email{irena@@mail.yacc.it}
+Win32 port with Borland compiler. @code{mysqlshutdown.exe} and
+@code{mysqlwatch.exe}
+@item David J. Hughes
+For the effort to make a shareware SQL database. We at TcX started with
+@code{mSQL}, but found that it couldn't satisfy our purposes so instead we
+wrote a SQL interface to our application builder Unireg. @code{mysqladmin}
+and @code{mysql} are programs that were largely influenced by their
+@code{mSQL} counterparts. We have put a lot of effort into making the
+@strong{MySQL} syntax a superset of @code{mSQL}. Many of the APIs ideas are
+borrowed from @code{mSQL} to make it easy to port free @code{mSQL} programs
+to @strong{MySQL}. @strong{MySQL} doesn't contain any code from @code{mSQL}.
+Two files in the distribution (@file{client/insert_test.c} and
+@file{client/select_test.c}) are based on the corresponding (non-copyrighted)
+files in the @code{mSQL} distribution, but are modified as examples showing
+the changes necessary to convert code from @code{mSQL} to @strong{MySQL}.
+(@code{mSQL} is copyrighted David J. Hughes.)
+@item 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).
+@item Richard A. O'Keefe
+For his public domain string library.
+@item Henry Spencer
+For his regex library, used in @code{WHERE column REGEXP regexp}.
+@item Free Software Foundation
+From whom we got an excellent compiler (@code{gcc}), the @code{libc} library
+(from which we have borrowed @file{strto.c} to get some code working in Linux)
+and the @code{readline} library (for the @code{mysql} client).
+@item Free Software Foundation & The XEmacs development team
+For a really great editor/environment used by almost everybody at
+TcX/MySQL AB/detron.
+@item Patrick Lynch
+For helping us acquire @code{http://www.mysql.com/}.
+@item Fred Lindberg
+For setting up qmail to handle @strong{MySQL} mailing list and for the
+incredible help we got in managing the @strong{MySQL} mailing lists.
+@item Igor Romanenko @email{igor@@frog.kiev.ua}
+@code{mysqldump} (previously @code{msqldump}, but ported and enhanced by
+Monty).
+@item Tim Bunce, Alligator Descartes
+For the @code{DBD} (Perl) interface.
+@item Andreas Koenig @email{a.koenig@@mind.de}
+For the Perl interface to @strong{MySQL}.
+@item Eugene Chan @email{eugene@@acenet.com.sg}
+For porting PHP to @strong{MySQL}.
+@item Michael J. Miller Jr. @email{mke@@terrapin.turbolift.com}
+For the first @strong{MySQL} manual. And a lot of spelling/language
+fixes for the FAQ (that turned into the @strong{MySQL} manual a long
+time ago).
+@item Giovanni Maruzzelli @email{maruzz@@matrice.it}
+For porting iODBC (Unix ODBC).
+@item 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 (see @file{mit-pthreads/Changes-mysql}).
+@item Xavier Leroy @email{Xavier.Leroy@@inria.fr}
+The author of LinuxThreads (used by @strong{MySQL} on Linux).
+@item Zarko Mocnik @email{zarko.mocnik@@dem.si}
+Sorting for Slovenian language and the @file{cset.tar.gz} module that makes
+it easier to add other character sets.
+@item "TAMITO" @email{tommy@@valley.ne.jp}
+The @code{_MB} character set macros and the ujis and sjis character sets.
+@item Joshua Chamas @email{joshua@@chamas.com}
+Base for concurrent insert, extended date syntax, debugging on NT and
+answering on the @strong{MySQL} mailing list.
+@item Yves Carlier @email{Yves.Carlier@@rug.ac.be}
+@code{mysqlaccess}, a program to show the access rights for a user.
+@item Rhys Jones @email{rhys@@wales.com} (And GWE Technologies Limited)
+For the JDBC, a module to extract data from @strong{MySQL} with a Java
+client.
+@item Dr Xiaokun Kelvin ZHU @email{X.Zhu@@brad.ac.uk}
+Further development of the JDBC driver and other @strong{MySQL}-related
+Java tools.
+@item James Cooper @email{pixel@@organic.com}
+For setting up a searchable mailing list archive at his site.
+@item Rick Mehalick @email{Rick_Mehalick@@i-o.com}
+For @code{xmysql}, a graphical X client for @strong{MySQL}.
+@item Doug Sisk @email{sisk@@wix.com}
+For providing RPM packages of @strong{MySQL} for RedHat Linux.
+@item Diemand Alexander V. @email{axeld@@vial.ethz.ch}
+For providing RPM packages of @strong{MySQL} for RedHat Linux-Alpha.
+@item Antoni Pamies Olive @email{toni@@readysoft.es}
+For providing RPM versions of a lot of @strong{MySQL} clients for Intel
+and SPARC.
+@item Jay Bloodworth @email{jay@@pathways.sde.state.sc.us}
+For providing RPM versions for @strong{MySQL} 3.21 versions.
+@item Jochen Wiedmann @email{wiedmann@@neckar-alb.de}
+For maintaining the Perl @code{DBD::mysql} module.
+@item Therrien Gilbert @email{gilbert@@ican.net}, Jean-Marc Pouyot @email{jmp@@scalaire.fr}
+French error messages.
+@item Petr snajdr, @email{snajdr@@pvt.net}
+Czech error messages.
+@item Jaroslaw Lewandowski @email{jotel@@itnet.com.pl}
+Polish error messages.
+@item Miguel Angel Fernandez Roiz
+Spanish error messages.
+@item Roy-Magne Mo @email{rmo@@www.hivolda.no}
+Norwegian error messages and testing of 3.21.#.
+@item Timur I. Bakeyev @email{root@@timur.tatarstan.ru}
+Russian error messages.
+@item @email{brenno@@dewinter.com} && Filippo Grassilli @email{phil@@hyppo.com}
+Italian error messages.
+@item Dirk Munzinger @email{dirk@@trinity.saar.de}
+German error messages.
+@item Billik Stefan @email{billik@@sun.uniag.sk}
+Slovak error messages.
+@item Stefan Saroiu @email{tzoompy@@cs.washington.edu}
+Romanian error messages.
+@item Peter Feher
+Hungarian error messages
+@item David Sacerdote @email{davids@@secnet.com}
+Ideas for secure checking of DNS hostnames.
+@item Wei-Jou Chen @email{jou@@nematic.ieo.nctu.edu.tw}
+Some support for Chinese(BIG5) characters.
+@item Wei He @email{hewei@@mail.ied.ac.cn}
+A lot of functionality for the Chinese(GBK) character set.
+@item Zeev Suraski @email{bourbon@@netvision.net.il}
+@code{FROM_UNIXTIME()} time formatting, @code{ENCRYPT()} functions, and
+@code{bison} advisor.
+Active mailing list member.
+@item Luuk de Boer @email{luuk@@wxs.nl}
+Ported (and extended) the benchmark suite to @code{DBI}/@code{DBD}. Have
+been of great help with @code{crash-me} and running benchmarks. Some new
+date functions. The mysql_setpermissions script.
+@item Jay Flaherty @email{fty@@utk.edu}
+Big parts of the Perl @code{DBI}/@code{DBD} section in the manual.
+@item Paul Southworth @email{pauls@@etext.org}, Ray Loyzaga @email{yar@@cs.su.oz.au}
+Proof-reading of the Reference Manual.
+@item Alexis Mikhailov @email{root@@medinf.chuvashia.su}
+User definable functions (UDFs); @code{CREATE FUNCTION} and
+@code{DROP FUNCTION}.
+@item Andreas F. Bobak @email{bobak@@relog.ch}
+The @code{AGGREGATE} extension to UDF functions.
+@item Ross Wakelin @email{R.Wakelin@@march.co.uk}
+Help to set up InstallShield for @strong{MySQL}-Win32.
+@item Jethro Wright III @email{jetman@@li.net}
+The @file{libmysql.dll} library.
+@item James Pereria @email{jpereira@@iafrica.com}
+Mysqlmanager, a Win32 GUI tool for administrating @strong{MySQL}.
+@item Curt Sampson @email{cjs@@portal.ca}
+Porting of MIT-pthreads to NetBSD/Alpha and NetBSD 1.3/i386.
+@item Sinisa Milivojevic @email{sinisa@@coresinc.com}
+Compression (with @code{zlib}) to the client/server protocol.
+Perfect hashing for the lexical analyzer phase.
+@item Antony T. Curtis @email{antony.curtis@@olcs.net}
+Porting of @strong{MySQL} to OS/2.
+@item Martin Ramsch @email{m.ramsch@@computer.org}
+Examples in the @strong{MySQL} Tutorial.
+@item Tim Bunce
+Author of @code{mysqlhotcopy}.
+@item Steve Harvey
+For making @code{mysqlaccess} more secure.
+@item Jeremy Cole @email{jeremy@@spaceapes.com}
+Proofreading and editing this fine manual.
+@item Valueclick Inc.
+For sponsoring the optimize section in this manual.
+@end table
+
+Other contributors, bugfinders and testers: James H. Thompson, Maurizio
+Menghini, Wojciech Tryc, Luca Berra, Zarko Mocnik, Wim Bonis, Elmar
+Haneke, @email{jehamby@@lightside}, @email{psmith@@BayNetworks.COM},
+@email{duane@@connect.com.au}, Ted Deppner @email{ted@@psyber.com},
+Mike Simons, Jaakko Hyv@"atti.
+
+And lots of bug report/patches from the folks on the mailing list.
+
+And a big tribute to those that help us answer questions on the
+@code{mysql@@lists.mysql.com} mailing list:
+
+@table @asis
+@item Daniel Koch @email{dkoch@@amcity.com}
+Irix setup.
+@item Luuk de Boer @email{luuk@@wxs.nl}
+Benchmark questions.
+@item Tim Sailer @email{tps@@users.buoy.com}
+@code{DBD-mysql} questions.
+@item Boyd Lynn Gerber @email{gerberb@@zenez.com}
+SCO related questions.
+@item Richard Mehalick @email{RM186061@@shellus.com}
+@code{xmysql}-related questions and basic installation questions.
+@item Zeev Suraski @email{bourbon@@netvision.net.il}
+Apache module configuration questions (log & auth), PHP-related
+questions, SQL syntax related questions and other general questions.
+@item Francesc Guasch @email{frankie@@citel.upc.es}
+General questions.
+@item Jonathan J Smith @email{jsmith@@wtp.net}
+Questions pertaining to OS-specifics with Linux, SQL syntax, and other
+things that might be needing some work.
+@item David Sklar @email{sklar@@student.net}
+Using @strong{MySQL} from PHP and Perl.
+@item Alistair MacDonald @email{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 @code{mysqlbug}.
+@item John Lyon @email{jlyon@@imag.net}
+Questions about installing @strong{MySQL} on Linux systems, using either
+@file{.rpm} files, or compiling from source.
+@item Lorvid Ltd. @email{lorvid@@WOLFENET.com}
+Simple billing/license/support/copyright issues.
+@item Patrick Sherrill @email{patrick@@coconet.com}
+ODBC and VisualC++ interface questions.
+@item Randy Harmon @email{rjharmon@@uptimecomputers.com}
+@code{DBD}, Linux, some SQL syntax questions.
+@end table
+
+@node News, Bugs, Credits, Top
+@appendix MySQL change history
+
+Note that we tend to update the manual at the same time we implement new
+things to @strong{MySQL}. If you find a version listed below that you can't
+find on the
+@uref{http://www.mysql.com/downloads/,@strong{MySQL} download page},
+this means that the version has not yet been released!
+
+@menu
+* News-3.23.x:: Changes in release 3.23.x (Released as alpha)
+* News-3.22.x:: Changes in release 3.22.x (Recommended version)
+* News-3.21.x:: Changes in release 3.21.x
+* News-3.20.x:: Changes in release 3.20.x
+* News-3.19.x:: Changes in release 3.19.x
+@end menu
+
+@node News-3.23.x, News-3.22.x, News, News
+@appendixsec Changes in release 3.23.x (Released as alpha)
+
+The major difference between release 3.23 and releases 3.22 and 3.21 is that
+3.23 contains a new ISAM library (MyISAM), which is more tuned for SQL
+than the old ISAM was.
+
+The 3.23 release is under development, and things will be added at a
+fast pace to it. For the moment we recommend this version only for
+users that desperately need a new feature that is found only in this
+release (like big file support and machine-independent tables). (Note
+that all new functionality in @strong{MySQL} 3.23 is extensively tested, but as
+this release involves much new code, it's difficult to test everything).
+
+We are not adding any more new features that are likely to break any
+old code in @strong{MySQL} 3.23 so this version should stabilise pretty soon
+and will soon be declared beta, gamma and release.
+
+@menu
+* News-3.23.22:: Changes in release 3.23.22
+* News-3.23.21:: Changes in release 3.23.21
+* News-3.23.20:: Changes in release 3.23.20
+* News-3.23.19:: Changes in release 3.23.19
+* News-3.23.18:: Changes in release 3.23.18
+* News-3.23.17:: Changes in release 3.23.17
+* News-3.23.16:: Changes in release 3.23.16
+* News-3.23.15:: Changes in release 3.23.15
+* News-3.23.14:: Changes in release 3.23.14
+* News-3.23.13:: Changes in release 3.23.13
+* News-3.23.12:: Changes in release 3.23.12
+* News-3.23.11:: Changes in release 3.23.11
+* News-3.23.10:: Changes in release 3.23.10
+* News-3.23.9:: Changes in release 3.23.9
+* News-3.23.8:: Changes in release 3.23.8
+* News-3.23.7:: Changes in release 3.23.7
+* News-3.23.6:: Changes in release 3.23.6
+* News-3.23.5:: Changes in release 3.23.5
+* News-3.23.4:: Changes in release 3.23.4
+* News-3.23.3:: Changes in release 3.23.3
+* News-3.23.2:: Changes in release 3.23.2
+* News-3.23.1:: Changes in release 3.23.1
+* News-3.23.0:: Changes in release 3.23.0
+@end menu
+
+@node News-3.23.22, News-3.23.21, News-3.23.x, News-3.23.x
+@appendixsubsec Changes in release 3.23.22
+@itemize @bullet
+@item
+Fixed that @code{lex_hash.h} is created properly for each @code{MySQL}
+distribution.
+@item
+Fixed that @code{MASTER} and @code{COLLECTION} are not a reserved words.
+@item
+The log generated by @code{--slow-query-log} didn't contain the whole queries.
+@item
+Fixed that open transactions in BDB tables are rolled back if the
+connection is closed unexpectedly.
+@item
+Added workaround for a bug in gcc 2.96 (intel) and gcc 2.9 (Ia64) in
+gen_lex_hash.c.
+@item
+Fixed memory leak in the client library when using @code{host=..} in the
+@code{my.cnf} file.
+@item
+Optimized functions that manipulates the hours/minutes/seconds.
+@item
+Fixed bug when comparing the result of @code{DATE_ADD}/@code{DATE_SUB}
+against a number
+@item
+Changed the meaning of @code{-F, --fast} for @code{myisamchk}. Added option
+@code{-C, --check-only-changed} to @code{myisamchk}.
+@item
+Added @code{ANALYZE table_name} to update key statistics for tables.
+@item
+Changed binary items @code{0x...} to be default regarded as an integer
+@item
+Fix for SCO and @code{show proesslist}.
+@item
+Added @code{auto-rehash} on reconnect for the @code{mysql} client.
+@end itemize
+
+@node News-3.23.21, News-3.23.20, News-3.23.22, News-3.23.x
+@appendixsubsec Changes in release 3.23.21
+@itemize @bullet
+@item
+Added @code{mysql_character_set_name(MYSQL *mysql)} function to the MySQL API.
+@item
+Made the update log @code{ASCII 0} safe.
+@item
+Added the @code{mysql_config} script.
+@item
+Fixed problem when using @code{<} or @code{>} with a char column that was only
+partly indexed.
+@item
+One would get a core dump if the log file was not readable by the MySQL user.
+@item
+Changed @code{mysqladmin} to use the @code{CREATE DATABASE}/@code{DROP
+DATABASE} commands instead of the old deprecated API calls.
+@item
+Fixed @code{chown} warning in @code{safe_mysqld}.
+@item
+Fixed a bug in @code{ORDER BY} that was introduced in 3.23.19.
+@item
+Only optimize the @code{DELETE FROM table_name} to do a drop+create of
+the table if we are in @code{AUTOCOMMIT} mode. (Needed for BDB tables).
+@item
+Added extra checks to avoid index corruption when the @code{ISAM}/@code{MyISAM}
+index files gets full during an @code{INSERT}/@code{UPDATE}.
+@item
+@code{myisamchk} didn't correctly update row checksum when used with
+@code{-ro} (This only gave an warning in subsequent runs).
+@item
+Fixed bug in @code{REPAIR TABLE} so that it works with tables without index.
+@item
+Fixed buffer overrun in @code{DROP DATABASE}
+@item
+@code{LOAD TABLE FROM MASTER} is sufficiently bug-free to announce it as
+a feature.
+@item
+@code{MATCH} and @code{AGAINST} are now reserved words.
+@end itemize
+
+@node News-3.23.20, News-3.23.19, News-3.23.21, News-3.23.x
+@appendixsubsec Changes in release 3.23.20
+@itemize @bullet
+@item
+Fixed bug in 3.23.19; @code{DELETE FROM table_name} removed the .frm file.
+@end itemize
+
+@node News-3.23.19, News-3.23.18, News-3.23.20, News-3.23.x
+@appendixsubsec Changes in release 3.23.19
+@itemize @bullet
+@item
+Changed copyright for all files to GPL for the server code and utilities and
+LGPL for the client libraries.
+@item
+Fixed bug where all rows matching weren't updated on a @code{MyISAM} table
+when doing update based on key on a table with many keys and some key changed
+values.
+@item
+The Linux @strong{MySQL} RPM's and binaries are now staticly linked with
+a linuxthread version that has faster mutex handling when used with
+@strong{MySQL}.
+@item
+@code{ORDER BY} can now uses @code{REF} keys to find subset the rows
+that needs to be sorted.
+@item
+Changed name of @code{print_defaults} to @code{my_print_defaults} to avoid
+name confusion.
+@item
+Fixed @code{NULLIF()} to work according to ANSI SQL99.
+@item
+Added @code{net_read_timeout} and @code{net_write_timeout} as startup
+parameters to @code{mysqld}.
+@item
+Fixed bug that destroyed index when doing @code{myisamchk --sort-records}
+on a table with prefix compressed index.
+@item
+Added pack_isam and myisampack to the standard @strong{MySQL} distribution.
+@item
+Added the syntax @code{BEGIN WORK} (the same as @code{BEGIN}).
+@item
+Fixed core dump bug when using @code{ORDER BY} on a @code{CONV()} expression.
+@item Added @code{LOAD TABLE FROM MASTER}
+@item Added @code{FLUSH MASTER} and @code{FLUSH SLAVE}
+@item Fixed big/little endian problem in the replication
+@end itemize
+
+@node News-3.23.18, News-3.23.17, News-3.23.19, News-3.23.x
+@appendixsubsec Changes in release 3.23.18
+@itemize @bullet
+@item
+Fixed a problem from 3.23.17 when choosing character set on the client side.
+@item
+Added @code{FLUSH TABLES WITH READ LOCK} to make a global lock suitable to
+make a copy of @strong{MySQL} data files.
+@item
+@code{CREATE TABLE ... SELECT ... PROCEDURE} now works.
+@item
+Internal temporary tables will now uses compressed index when using
+@code{GROUP BY} on @code{VARCHAR/CHAR} columns.
+@item
+Fixed a problem when locking the same table with both a @code{READ} and a
+@code{WRITE} lock.
+@item
+Fixed problem with myisamchk and @code{RAID} tables.
+@end itemize
+
+@node News-3.23.17, News-3.23.16, News-3.23.18, News-3.23.x
+@appendixsubsec Changes in release 3.23.17
+@itemize @bullet
+@item
+Fixed a bug in @code{find_in_set()} when the first argument was @code{NULL}.
+@item
+Added table locks to Berkeley DB.
+@item
+Fixed a bug with @code{LEFT JOIN} and @code{ORDER BY} where the first
+table had only one matching row.
+@item
+Added 4 sample @code{my.cfg} example files in the @file{support-files}
+directory.
+@item
+Fixed @code{duplicated key} problem when doing big @code{GROUP BY}'s.
+(This bug was probably introduced in 3.23.15).
+@item
+Changed syntax for @code{INNER JOIN} to match ANSI SQL.
+@item
+Added @code{NATURAL JOIN} syntax.
+@item
+A lot of fixes in the @code{BDB} interface.
+@item
+Added handling of @code{--no-defaults} and @code{--defaults-file} to
+@code{safe_mysqld.sh} and @code{mysql_install_db.sh}.
+@item
+Fixed bug in reading compressed tables with many threads.
+@item
+Fixed that @code{USE INDEX} works with @code{PRIMARY} keys.
+@item
+Added @code{BEGIN} statement to start a transaction in @code{AUTOCOMMIT} mode.
+@item
+Added symbolic links support for Win32.
+@item
+Changed protocol to let client know if the server is in AUTOCOMMIT mode
+and if there is a pending transaction. If there is a pending transaction
+the client library will give an error before reconnecting to the server to
+let the client know that the server did a rollback.
+The protocol is still backward compatible with old clients
+@item
+@code{KILL} now works on a thread that is locked on a 'write' to a dead client.
+@item
+Fixed memory leak in the replication slave thread.
+@item
+Added new option @code{log-slave-updates} to allow daisy-chaining the slaves.
+@item
+Fixed compile error on FreeBSD and other systems where @code{pthread_t}
+is not the same as @code{int}.
+@item
+Fixed master shutdown aborting the slave thread.
+@item
+Fixed a race condition in @code{INSERT DELAYED} code when doing
+@code{ALTER TABLE}.
+@item
+Added deadlock detection sanity checks to @code{INSERT DELAYED}
+@end itemize
+
+@node News-3.23.16, News-3.23.15, News-3.23.17, News-3.23.x
+@appendixsubsec Changes in release 3.23.16
+@itemize @bullet
+@item
+Added option @code{TYPE=QUICK} to @code{CHECK} and @code{REPAIR}.
+@item
+Fixed bug in @code{REPAIR TABLE} when the table was in use by other threads.
+@item
+Added a thread cache to make it possible to debug @strong{MySQL} with
+@code{gdb} when one does a lot of reconnects. This will also improve
+systems where you can't use persistent connections.
+@item
+Lots of fixes in the Berekely DB interface.
+@item
+@code{UPDATE IGNORE} will not abort if an update results in a
+@code{DUPLICATE_KEY} error.
+@item
+Put @code{CREATE TEMPORARY TABLE} commands in the update log.
+@item
+Fixed bug in handling of masked IP numbers in the privilege tables.
+@item
+Fixed bug with @code{delayed_key_writes} tables and @code{CHECK TABLE}.
+@item
+Added @code{replicate-do-db} and @code{replicate-ignore-db} options to
+restrict which databases get replicated
+@item
+Added @code{SQL_LOG_BIN} option
+@end itemize
+
+@node News-3.23.15, News-3.23.14, News-3.23.16, News-3.23.x
+@appendixsubsec Changes in release 3.23.15
+@itemize @bullet
+@item
+To start @code{mysqld} as @code{root}, you must now use the @code{--user=root} option.
+@item
+Added interface to Berkeley DB. (This is not yet functional; Play with it at
+your own risk!)
+@item
+Replication between master and slaves.
+@item
+Fixed bug that other threads could steal a lock when a thread had
+a lock on a table and did a @code{FLUSH TABLES} command.
+@item
+Added the @code{slow_launch_time} variable and the @code{Slow_launch_threads}
+status variable to @code{mysqld}. These can be examined with
+@code{mysqladmin variables} and @code{mysqladmin extended-status}.
+@item
+Added functions @code{INET_NTOA()} and @code{INET_ATON()}.
+@item
+The default type of @code{IF()} now depends on the second and
+third arguments and not only on the second argument.
+@item
+Fixed case when @code{myisamchk} could go into a loop when trying to
+repair a crashed table.
+@item
+Don't write @code{INSERT DELAYED} to update log if @code{SQL_LOG_UPDATE=0}.
+@item
+Fixed problem with @code{REPLACE} on @code{HEAP} tables.
+@item
+Added possible character sets and time zone to @code{SHOW VARIABLES}.
+@item
+Fixed bug in locking code that could result it locking problems with
+concurrent inserts under high load.
+@item
+Fixed a problem with @code{DELETE} of many rows on a table with
+compressed keys where @strong{MySQL} scanned the index to find the rows.
+@item
+Fixed problem with @code{CHECK} on table with deleted keyblocks.
+@item
+Fixed a bug in reconnect (at the client side) where it didn't free memory
+properly in some contexts.
+@item
+Fixed problems in update log when using @code{LAST_INSERT_ID()} to update
+a table with an auto_increment key.
+@item
+Added function @code{NULLIF()}.
+@item
+Fixed bug when using @code{LOAD DATA INFILE} on a table with
+@code{BLOB/TEXT} columns.
+@item
+Optimised MyISAM to be faster when inserting keys in sorted order.
+@item
+@code{EXPLAIN SELECT..} now also prints out whether @strong{MySQL} needs to
+create a temporary table or use file sorting when resolving the @code{SELECT}.
+@item
+Added optimization to skip @code{ORDER BY} parts where the part is a
+constant expression in the @code{WHERE} part. Indexes can now be used
+even if the @code{ORDER BY} doesn't match the index exactly, as long as
+all the not used index parts and all the extra @code{ORDER BY}
+columns are constants in the @code{WHERE} clause. @xref{MySQL indexes}.
+@item
+@code{UPDATE} and @code{DELETE} on a whole unique key in the @code{WHERE} part,
+is now faster than before.
+@item
+Changed @code{RAID_CHUNKSIZE} to be in 1024 byte increments.
+@item
+Fixed coredump in LOAD_FILE(NULL).
+@end itemize
+
+@node News-3.23.14, News-3.23.13, News-3.23.15, News-3.23.x
+@appendixsubsec Changes in release 3.23.14
+@itemize @bullet
+@item
+Fixed a bug in @code{CONCAT()} where one of the arguments was a function
+that returned a modified argument.
+@item
+Fixed a critical bug in @code{myisamchk}, where it updated the header in
+the index file when one only checked the table. This confused the
+@code{mysqld} daemon if it updated the same table at the same time. Now
+the status in the index file is only updated if one uses
+@code{--update-state}. With older @code{myisamchk} versions you should
+use @code{--read-only} when only checking tables, if there is the
+slightest chance that the @code{mysqld} server is working on the table at the
+same time!
+@item
+Fixed that @code{DROP TABLE} is logged in the update log.
+@item
+Fixed problem when searching on @code{DECIMAL()} key field
+where the column data contained leading zeros.
+@item
+Fix bug in @code{myisamchk} when the auto_increment isn't the first key.
+@item
+Allow @code{DATETIME} in ISO8601 format: 2000-03-12T12:00:00
+@item
+Dynamic character sets. A @code{mysqld} binary can now handle many different
+character sets (you can choose which when starting @code{mysqld}).
+@item
+Added command @code{REPAIR TABLE}.
+@item
+Added C API function @code{mysql_thread_safe()}.
+@item
+Added the @code{UMASK_DIR} environment variable.
+@item
+Added function @code{CONNECTION_ID()}.
+@item
+When using @code{=} on @code{BLOB} or @code{VARCHAR BINARY} keys, where
+only a part of the column was indexed, the whole column of the result
+row wasn't compared.
+@item
+Fix for sjis character set and @code{ORDER BY}.
+@item
+When running in ANSI mode, don't allow columns to be used that aren't in
+the @code{GROUP BY} part.
+@end itemize
+
+@node News-3.23.13, News-3.23.12, News-3.23.14, News-3.23.x
+@appendixsubsec Changes in release 3.23.13
+@itemize @bullet
+@item
+Fixed problem when doing locks on the same table more than 2 times in
+the same @code{LOCK TABLE} command; This fixed the problem one got when running
+the test-ATIS test with @code{--fast} or @code{--check-only-changed}.
+@item
+Added option @code{SQL_BUFFER_RESULT} to @code{SELECT}.
+@item
+Removed end space from double/float numbers in results from temporary
+tables.
+Added @code{CHECK TABLE} command.
+@item
+Added changes for MyISAM in 3.23.12 that didn't get into the source
+distribution because of CVS problems.
+@item
+Fixed bug so that mysqladmin shutdown will wait for the local server to close
+down.
+@item
+Fixed a possible endless loop when calculating timestamp.
+@item
+Added print_defaults to the .rpm files. Removed mysqlbug from the client
+rpm file.
+@end itemize
+
+@node News-3.23.12, News-3.23.11, News-3.23.13, News-3.23.x
+@appendixsubsec Changes in release 3.23.12
+@itemize @bullet
+@item
+Fixed bug in @code{MyISAM} involving @code{REPLACE ... SELECT} which could
+give a corrupted table.
+@item
+Fixed bug in @code{myisamchk} where it wrongly reset the auto_increment value.
+@item
+LOTS of patches for Linux Alpha. @strong{MySQL} now appears to be relatively
+stable on Alpha.
+@item
+Changed @code{DISTINCT} on @code{HEAP} temporary tables to use hashed
+keys to quickly find duplicated rows. This mostly concerns queries of
+type @code{SELECT DISTINCT ... GROUP BY ..}. This fixes a problem where
+not all duplicates were removed in queries of the above type. In
+addition, the new code is MUCH faster.
+@item
+Added patches to make @code{MySQL} compile on MacOS X.
+@item
+Added option @code{IF NOT EXISTS} to @code{CREATE DATABASE}.
+@item
+Added options @code{--all-databases} and @code{--databases} to @code{mysqldump}
+to allow dumping of many databases at the same time.
+@item
+Fixed bug in compressed @code{DECIMAL()} index in @code{MyISAM} tables.
+@item
+Fixed bug when storing 0 into a timestamp.
+@item
+When doing @code{mysqladmin shutdown} on a local connection, @code{mysqladmin} now
+waits until the pidfile is gone before terminating.
+@item
+Fixed core dump with some @code{COUNT(DISTINCT ...)} queries.
+@item
+Fixed that @code{myisamchk} works properly with RAID:ed tables.
+@item
+Fixed problem with @code{LEFT JOIN} and @code{key_field IS NULL}.
+@item
+Fixed bug in @code{net_clear()} which could give the error @code{Aborted
+connection} in the @strong{MySQL} clients.
+@item
+Added options @code{USE INDEX (key_list)} and @code{IGNORE INDEX (key_list)} as
+join parameters in @code{SELECT}.
+@item
+@code{DELETE} and @code{RENAME} should now work on @code{RAID} tables.
+@end itemize
+
+@node News-3.23.11, News-3.23.10, News-3.23.12, News-3.23.x
+@appendixsubsec Changes in release 3.23.11
+@itemize @bullet
+@item
+Allow the @code{ALTER TABLE tbl_name ADD (field_list)} syntax.
+@item
+Fixed problem with optimizer that could sometimes use wrong keys.
+@item
+Fixed that @code{GRANT/REVOKE ALL PRIVILEGES} doesn't affect
+@code{GRANT OPTION}.
+@item
+Removed extra @code{)} from the output of @code{SHOW GRANTS}
+@item
+Fixed problem when storing numbers in timestamps.
+@item
+Fix problem with timezones that have half hour offsets.
+@item
+Allow the syntax @code{UNIQUE INDEX} in @code{CREATE} statements.
+@item
+@code{mysqlhotcopy} - fast on-line hot-backup utility for local
+@strong{MySQL} databases. By Tim Bunce.
+@item
+New more secure @code{mysqlaccess}. Thanks to Steve Harvey for this.
+@item
+Added options @code{--i-am-a-dummy} and @code{--safe-updates} to @code{mysql}.
+@item
+Added variables @code{select_limit} and @code{max_join_size} to @code{mysql}.
+@item
+Added sql variables: @code{SQL_MAX_JOIN_SIZE} and @code{SQL_SAFE_UPDATES}.
+@item
+Added @code{READ LOCAL} lock that doesn't lock the table for concurrent
+inserts. (This is used by @code{mysqldump}).
+@item
+Changed that @code{LOCK TABLES .. READ} doesn't anymore allow concurrent
+inserts.
+@item
+Added option @code{--skip-delay-key-write} to @code{mysqld}.
+@item
+Fixed security problem in the protocol regarding password checking.
+@item
+@code{_rowid} can now be used as an alias for an integer type unique indexed
+column.
+@item
+Added back blocking of @code{SIGPIPE} when compiling with @code{--thread-safe-clients}
+to make things safe for old clients.
+@end itemize
+
+@node News-3.23.10, News-3.23.9, News-3.23.11, News-3.23.x
+@appendixsubsec Changes in release 3.23.10
+@itemize @bullet
+@item
+Fixed bug in 3.23.9 where memory wasn't properly freed when doing
+@code{LOCK TABLES}.
+@end itemize
+
+@node News-3.23.9, News-3.23.8, News-3.23.10, News-3.23.x
+@appendixsubsec Changes in release 3.23.9
+@itemize @bullet
+@item
+Fixed problem that affected queries that did arithmetic on group functions.
+@item
+Fixed problem with timestamps and @code{INSERT DELAYED}.
+@item
+Fixed that @code{date_column BETWEEN const_date AND const_date} works.
+@item
+Fixed problem when only changing a 0 to @code{NULL} in a table with
+@code{BLOB/TEXT} columns.
+@item
+Fixed bug in range optimizer when using many key parts and or on the middle
+key parts: @code{WHERE K1=1 and K3=2 and (K2=2 and K4=4 or K2=3 and K4=5)}
+@item
+Added command @code{source} to @code{mysql} to allow reading of batch files
+inside the @code{mysql} client. Original patch by Matthew Vanecek.
+@item
+Fixed critical problem with the @code{WITH GRANT OPTION} option.
+@item
+Don't give an unnecessary @code{GRANT} error when using tables from many
+databases in the same query.
+@item
+Added VIO wrapper (needed for SSL support ; By Andrei Errapart and
+Tõnu Samuel).
+@item
+Fixed optimizer problem on @code{SELECT} when using many overlapping indexes.
+@strong{MySQL} should now be able to choose keys even better when there
+is many keys to choose from.
+@item
+Changed optimizer to prefer a range key instead of a ref key when the
+range key can uses more columns than the ref key (which only can use
+columns with =). For example, the following type of queries should now
+be faster: @code{SELECT * from key_part_1=const and key_part_2 > const2}
+@item
+Fixed bug that a change of all @code{VARCHAR} columns to @code{CHAR} columns
+didn't change row type from dynamic to fixed.
+@item
+Disabled floating point exceptions for FreeBSD to fix core dump when
+doing @code{SELECT floor(pow(2,63))}.
+@item
+Changed @code{mysqld} startup option @code{--delay-key-write} to
+@code{--delay-key-write-for-all-tables}
+@item
+Added @code{read-next-on-key} to @code{HEAP} tables. This should fix all
+problems with @code{HEAP} tables when using not @code{UNIQUE} keys.
+@item
+Added print of default arguments options to all clients.
+@item
+Added @code{--log-slow-queries} to @code{mysqld} to log all queries that take a
+long time to a separate log file with a time of how long the query took.
+@item
+Fixed core dump when doing @code{WHERE key_column=RAND(...)}
+@item
+Fixed optimization bug in @code{SELECT .. LEFT JOIN ... key_column IS NULL},
+when @code{key_column} could contain @code{NULL} values.
+@item
+Fixed problem with 8-bit characters as separators in @code{LOAD DATA INFILE}.
+@item
+
+@end itemize
+
+@node News-3.23.8, News-3.23.7, News-3.23.9, News-3.23.x
+@appendixsubsec Changes in release 3.23.8
+@itemize @bullet
+@item
+Fixed problem when handling indexfiles larger than 8G.
+@item
+Added latest patches to mit-pthreads for NetBSD.
+@item
+Fixed problem with timezones that are < GMT -11.
+@item
+Fixed a bug when deleting packed keys in @code{NISAM}.
+@item
+Fixed problem with @code{ISAM} when doing some @code{ORDER BY ... DESC} queries.
+@item
+Fixed bug when doing a join on a text key which didn't cover the whole key.
+@item
+Option @code{--delay-key-write} didn't enable delayed key writing.
+@item
+Fixed update of @code{TEXT} column which only involved case changes.
+@item
+Fixed that @code{INSERT DELAYED} doesn't update timestamps that are given.
+@item
+Added function @code{YEARWEEK()} and options @code{x}, @code{X}, @code{v} and
+@code{V} to @code{DATE_FORMAT()}.
+@item
+Fixed problem with @code{MAX(indexed_column)} and HEAP tables.
+@item
+Fixed problem with @code{BLOB NULL} keys and @code{LIKE} "prefix%".
+@item
+Fixed problem with @code{MyISAM} and fixed length rows < 5 bytes.
+@item
+Fixed problem that could cause @strong{MySQL} to touch freed memory when
+doing very complicated @code{GROUP BY} queries.
+@item
+Fixed core dump if you got a crashed table where an @code{ENUM} field value
+was too big.
+@end itemize
+
+@node News-3.23.7, News-3.23.6, News-3.23.8, News-3.23.x
+@appendixsubsec Changes in release 3.23.7
+@itemize @bullet
+@item
+Fixed workaround under Linux to avoid problems with @code{pthread_mutex_timedwait},
+which is used with @code{INSERT DELAYED}. @xref{Linux}.
+@item
+Fixed that one will get a 'disk full' error message if one gets disk full
+when doing sorting (instead of waiting until we got more disk space).
+@item
+Fixed a bug in @code{MyISAM} with keys > 250 characters.
+@item
+In @code{MyISAM} one can now do an @code{INSERT} at the same time as other
+threads are reading from the table.
+@item
+Added variable @code{max_write_lock_count} to @code{mysqld} to force a
+@code{READ} lock after a certain number of @code{WRITE} locks.
+@item
+Inverted flag @code{delayed_key_write} on @code{show variables}.
+@item
+Renamed variable @code{concurrency} to @code{thread_concurrency}.
+@item
+The following functions are now multi-byte-safe:
+@code{LOCATE(substr,str)}, @code{POSITION(substr IN str)},
+@code{LOCATE(substr,str,pos)}, @code{INSTR(str,substr)},
+@code{LEFT(str,len)}, @code{RIGHT(str,len)},
+@code{SUBSTRING(str,pos,len)}, @code{SUBSTRING(str FROM pos FOR len)},
+@code{MID(str,pos,len)}, @code{SUBSTRING(str,pos)}, @code{SUBSTRING(str
+FROM pos)}, @code{SUBSTRING_INDEX(str,delim,count)}, @code{RTRIM(str)},
+@code{TRIM([[BOTH | TRAILING] [remstr] FROM] str)},
+@code{REPLACE(str,from_str,to_str)}, @code{REVERSE(str)},
+@code{INSERT(str,pos,len,newstr)}, @code{LCASE(str)}, @code{LOWER(str)},
+@code{UCASE(str)} and @code{UPPER(str)}; Patch by Wei He.
+@item
+Fix core dump when releasing a lock from a non-existant table.
+@item
+Remove locks on tables before starting to remove duplicates.
+@item
+Added option @code{FULL} to @code{SHOW PROCESSLIST}.
+@item
+Added option @code{--verbose} to @code{mysqladmin}.
+@item
+Fixed problem when automatically converting HEAP to MyISAM.
+@item
+Fixed bug in HEAP tables when doing insert + delete + insert + scan the
+table.
+@item
+Fixed bugs on Alpha with @code{REPLACE()} and @code{LOAD DATA INFILE}.
+@item
+Added @code{mysqld} variable @code{interactive_timeout}.
+@item
+Changed the argument to @code{mysql_data_seek()} from @code{ulong} to
+@code{ulonglong}.
+@end itemize
+
+@node News-3.23.6, News-3.23.5, News-3.23.7, News-3.23.x
+@appendixsubsec Changes in release 3.23.6
+
+@itemize @bullet
+@item
+Added @code{mysqld} option @code{-O lower_case_table_names=@{0|1@}} to allow
+users to force table names to lower case.
+@item
+Added @code{SELECT ... INTO DUMPFILE}.
+@item
+Added mysqld option @code{--ansi} to make some functions @code{ANSI SQL}
+compatible.
+@item
+Temporary tables now starts with @code{#sql}.
+@item
+Added quoting of identifiers with @code{`} (@code{"} in @code{--ansi} mode).
+@item
+Changed to use snprintf() when printing floats to avoid some buffer
+overflows on FreeBSD.
+@item
+Made @code{[floor()} overflow safe on FreeBSD.
+@item
+Added option @code{--quote-names} to @code{mysqldump}
+@item
+Fixed bug that one could make a part of a @code{PRIMARY KEY NOT NULL}.
+@item
+Fixed @code{encrypt()} to be thread safe and not reuse buffer.
+@item
+Added @code{mysql_odbc_escape_string()} function to support big5 characters in
+MyOBC.
+@item
+Rewrote the table handler to use classes. This introduces a lot of new code,
+but will make table handling faster and better.
+@item
+Added patch by Sasha for user defined variables.
+@item
+Changed that @code{FLOAT} and @code{DOUBLE} (without any length modifiers) are
+not anymore fixed decimal point numbers.
+@item
+Changed the meaning of @code{FLOAT(X)}: Now this is the same as @code{FLOAT} if
+X <= 24 and a @code{DOUBLE} if 24 < X <= 53.
+@item
+@code{DECIMAL(X)} is now an alias for @code{DECIMAL(X,0)} and @code{DECIMAL}
+is now an alias for @code{DECIMAL(10,0)}. The same goes for @code{NUMERIC}.
+@item
+Added option @code{ROW_FORMAT=@{default | dynamic | static | compressed@}} to
+@code{CREATE_TABLE}.
+@item
+@code{DELETE FROM table_name} didn't work on temporary tables.
+@item
+Changed function @code{CHAR_LENGTH()} to be multi-byte character safe.
+@item
+Added function @code{ORD(string)}.
+@end itemize
+
+@node News-3.23.5, News-3.23.4, News-3.23.6, News-3.23.x
+@appendixsubsec Changes in release 3.23.5
+
+@itemize @bullet
+@item
+Fixed some Y2K problems in the new date handling in 3.23.
+@item
+Fixed problem with @code{SELECT DISTINCT ... ORDER BY RAND()}.
+@item
+Added patches by Sergei A. Golubchik for text searching on the MyISAM level.
+@item
+Fixed cache overflow problem when using full joins without keys.
+@item
+Fixed some configure issues.
+@item
+Some small changes to make parsing faster.
+@item
+@code{ALTER TABLE} + adding a column after the last field didn't work.
+@item
+Fixed problem when using an auto_increment column in two keys
+@item
+One can now with MyISAM have the auto_increment part as a sub part:
+@code{CREATE TABLE foo (a int not null auto_increment, b char(5), primary key (b,a))}
+@item
+Fixed bug in MyISAM with packed char keys that could be @code{NULL}.
+@item
+@code{AS} on fieldname with @code{CREATE TABLE table_name SELECT ...} didn't
+work.
+@item
+Allow use of @code{NATIONAL} and @code{NCHAR} when defining character columns.
+This is the same as not using @code{BINARY}.
+@item
+Don't allow @code{NULL} columns in a @code{PRIMARY KEY} (only in @code{UNIQUE}
+keys).
+@item
+Clear @code{LAST_INSERT_ID} if one uses this in ODBC:
+@code{WHERE auto_increment_column IS NULL}. This seems to fix some problems
+with Access.
+@item
+@code{SET SQL_AUTO_IS_NULL=0|1} now turns on/off the handling of
+searching after the last inserted row with @code{WHERE
+auto_increment_column IS NULL}.
+@item
+Added new @code{mysqld} variable @code{concurrency} for Solaris.
+@item
+Added option @code{--relative} to @code{mysqladmin} to make
+@code{extended-status} more useful to monitor changes.
+@item
+Fixed bug when using @code{COUNT(DISTINCT..)} on an empty table.
+@item
+Added support for the Chinese character set GBK.
+@item
+Fixed problem with @code{LOAD DATA INFILE} and @code{BLOB} columns.
+@item
+Added bit operator @code{~} (negation).
+@item
+Fixed problem with @code{UDF} functions.
+@end itemize
+
+@node News-3.23.4, News-3.23.3, News-3.23.5, News-3.23.x
+@appendixsubsec Changes in release 3.23.4
+
+@itemize @bullet
+@item
+Inserting a @code{DATETIME} into a @code{TIME} column will not anymore
+try to store 'days' in it.
+@item
+Fixed problem with storage of float/double on little endian machines.
+(This affected @code{SUM()}.)
+@item
+Added connect timeout on TCP/IP connections.
+@item
+Fixed problem with @code{LIKE} "%" on an index that may have @code{NULL} values.
+@item
+@code{REVOKE ALL PRIVILEGES} didn't revoke all privileges.
+@item
+Allow creation of temporary tables with same name as the original table.
+@item
+When granting a user a grant option for a database, he couldn't grant
+privileges to other users.
+@item
+New command: @code{SHOW GRANTS FOR user} (by Sinisa).
+@item
+New @code{date_add} syntax: @code{date/datetime + INTERVAL # interval_type}.
+By Joshua Chamas.
+@item
+Fixed privilege check for @code{LOAD DATA REPLACE}.
+@item
+Automatic fixing of broken include files on Solaris 2.7
+@item
+Some configure issues to fix problems with big file system detection.
+@item
+@code{REGEXP} is now case insensitive if you use non-binary strings.
+@end itemize
+
+@node News-3.23.3, News-3.23.2, News-3.23.4, News-3.23.x
+@appendixsubsec Changes in release 3.23.3
+
+@itemize @bullet
+Added patches for MIT-pthreads on NetBSD.
+@item
+Fixed range bug in MyISAM.
+@item
+@code{ASC} is now the default again for @code{ORDER BY}.
+@item
+Added @code{LIMIT} to @code{UPDATE}.
+@item
+New client function: @code{mysql_change_user()}.
+@item
+Added character set to @code{SHOW VARIABLES}.
+@item
+Added support of @code{--[whitespace]} comments.
+@item
+Allow @code{INSERT into tbl_name VALUES ()}, that is, you may now specify
+an empty value list to insert a row in which each column is set to its
+default value.
+@item
+Changed @code{SUBSTRING(text FROM pos)} to conform to ANSI SQL. (Before this
+construct returned the rightmost 'pos' characters).
+@item
+@code{SUM(..)} with @code{GROUP BY} returned 0 on some systems.
+@item
+Changed output for @code{SHOW TABLE STATUS}.
+@item
+Added @code{DELAY_KEY_WRITE} option to @code{CREATE TABLE}.
+@item
+Allow @code{AUTO_INCREMENT} on any key part.
+@item
+Fixed problem with @code{YEAR(NOW())} and @code{YEAR(CURDATE())}.
+@item
+Added @code{CASE} construct.
+@item
+New function @code{COALESCE()}.
+@end itemize
+
+@node News-3.23.2, News-3.23.1, News-3.23.3, News-3.23.x
+@appendixsubsec Changes in release 3.23.2
+
+@itemize @bullet
+@item
+Fixed range optimizer bug: @code{SELECT * FROM table_name WHERE
+key_part1 >= const AND (key_part2 = const OR key_part2 = const)}. The
+bug was that some rows could be duplicated in the result.
+@item
+Running @code{myisamchk} without @code{-a} updated the index
+distribution wrong.
+@item
+@code{SET SQL_LOW_PRIORITY_UPDATES=1} gave parse error before.
+@item
+You can now update indexes columns that are used in the @code{WHERE} clause.
+@code{UPDATE tbl_name SET KEY=KEY+1 WHERE KEY > 100}
+@item
+Date handling should now be a bit faster.
+@item
+Added handling of fuzzy dates (dates where day or month is 0):
+(Like: 1999-01-00)
+@item
+Fixed optimization of @code{SELECT ... WHERE key_part1=const1 AND
+key_part_2=const2 AND key_part1=const4 AND key_part2=const4} ; Indextype
+should be @code{range} instead of @code{ref}.
+@item
+Fixed @code{egcs} 1.1.2 optimizer bug (when using @code{BLOB}s) on Linux Alpha.
+@item
+Fixed problem with @code{LOCK TABLES} combined with @code{DELETE FROM table}.
+@item
+MyISAM tables now allow keys on @code{NULL} and @code{BLOB/TEXT} columns.
+@item
+The following join is now much faster:
+@code{SELECT ... FROM t1 LEFT JOIN t2 ON ... WHERE t2.not_null_column IS NULL}.
+@item
+@code{ORDER BY} and @code{GROUP BY} can be done on functions.
+@item
+Changed handling of 'const_item' to allow handling of @code{ORDER BY RAND()}.
+@item
+Indexes are now used for @code{WHERE key_column = function}.
+@item
+Indexes are now used for @code{WHERE key_column = column_name} even if
+the columns are not identically packed.
+@item
+Indexes are now used for @code{WHERE column_name IS NULL}.
+@item
+Changed heap tables to be stored in low_byte_first order (to make it easy
+to convert to MyISAM tables)
+@item
+Automatic change of HEAP temporary tables to MyISAM tables in case of
+'table is full' errors.
+@item
+Added option @code{--init-file=file_name} to @code{mysqld}.
+@item
+@code{COUNT(DISTINCT value,[value,...])}
+@item
+@code{CREATE TEMPORARY TABLE} now creates a temporary table, in its own
+namespace, that is automatically deleted if connection is dropped.
+@item
+New reserved words (required for @code{CASE}): @code{CASE, THEN, WHEN, ELSE and END}.
+@item
+New functions @code{EXPORT_SET()} and @code{MD5()}.
+@item
+Support for the GB2312 Chinese character set.
+@end itemize
+
+@node News-3.23.1, News-3.23.0, News-3.23.2, News-3.23.x
+@appendixsubsec Changes in release 3.23.1
+
+@itemize @bullet
+@item
+Fixed some compilation problems.
+@end itemize
+
+@node News-3.23.0, , News-3.23.1, News-3.23.x
+@appendixsubsec Changes in release 3.23.0
+
+@itemize @bullet
+A new table handler library (@code{MyISAM}) with a lot of new features.
+@xref{MyISAM}.
+@item
+You can create in-memory @code{HEAP} tables which are extremely fast for
+lookups.
+@item
+Support for big files (63 bit) on OSes that support big files.
+@item
+New function @code{LOAD_FILE(filename)} to get the contents of a file as a
+string value.
+@item
+New operator @code{<=>} which will act as @code{=} but will return TRUE
+if both arguments are @code{NULL}. This is useful for comparing changes
+between tables.
+@item
+Added the ODBC 3.0 @code{EXTRACT(interval FROM datetime)} function.
+@item
+Columns defined as @code{FLOAT(X)} is not rounded on storage and may be
+in scientific notation (1.0 E+10) when retrieved.
+@item
+@code{REPLACE} is now faster than before.
+@item
+Changed @code{LIKE} character comparison to behave as @code{=};
+This means that @code{'e' LIKE '@'e'} is now true.
+@item
+@code{SHOW TABLE STATUS} returns a lot of information about the tables.
+@item
+Added @code{LIKE} to the @code{SHOW STATUS} command.
+@item
+Added privilege column to @code{SHOW COLUMNS}.
+@item
+Added columns @code{packed} and @code{comment} to @code{SHOW INDEX}.
+@item
+Added comments to tables (with @code{CREATE TABLE ... COMMENT "xxx"}).
+@item
+Added @code{UNIQUE}, as in
+@code{CREATE TABLE table_name (col int not null UNIQUE)}
+@item
+New create syntax: @code{CREATE TABLE table_name SELECT ....}
+@item
+New create syntax: @code{CREATE TABLE IF NOT EXISTS ...}
+@item
+Allow creation of @code{CHAR(0)} columns.
+@item
+@code{DATE_FORMAT()} now requires @samp{%} before any format character.
+@item
+@code{DELAYED} is now a reserved word (sorry about that :( ).
+@item
+An example procedure is added: @code{analyse}, file: @file{sql_analyse.c}.
+This will describe the data in your query. Try the following:
+@example
+SELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max elements,[max memory]])
+@end example
+
+This procedure is extremely useful when you want to check the data in your
+table!
+@item
+@code{BINARY} cast to force a string to be compared case sensitively.
+@item
+Added option @code{--skip-show-database} to @code{mysqld}.
+@item
+Check if a row has changed in an @code{UPDATE} now also works with
+@code{BLOB}/@code{TEXT} columns.
+@item
+Added the @code{INNER} join syntax. @strong{NOTE}: This made @code{INNER}
+a reserved word!
+@item
+Added support for netmasks to the hostname in the @strong{MySQL} tables.
+You can specify a netmask using the @code{IP/NETMASK} syntax.
+@item
+If you compare a @code{NOT NULL DATE/DATETIME} column with @code{IS
+NULL}, this is changed to a compare against @code{0} to satisfy some ODBC
+applications. (By @email{shreeve@@uci.edu}).
+@item
+@code{NULL IN (...)} now returns @code{NULL} instead of @code{0}. This will
+ensure that @code{null_column NOT IN (...)} doesn't match
+@code{NULL} values.
+@item
+Fix storage of floating point values in @code{TIME} columns.
+@item
+Changed parsing of @code{TIME} strings to be more strict. Now the
+fractional second part is detected (and currently skipped). The
+following formats are supported:
+@table @code
+@item [[DAYS] [H]H:]MM:]SS[.fraction]
+@item [[[[[H]H]H]H]MM]SS[.fraction]
+@end table
+@item
+Detect (and ignore) second fraction part from @code{DATETIME}.
+@item
+Added the @code{LOW_PRIORITY} attribute to @code{LOAD DATA INFILE}.
+@item
+The default index name now uses the same case as the used column name.
+@item
+Changed default number of connections to 100.
+@item
+Use bigger buffers when using @code{LOAD DATA INFILE}.
+@item
+@code{DECIMAL(x,y)} now works according to ANSI SQL.
+@item
+Added aggregate UDF functions. Thanks to Andreas F. Bobak
+@email{bobak@@relog.ch} for this!
+@item
+@code{LAST_INSERT_ID()} is now updated for @code{INSERT INTO ... SELECT}.
+@item
+Some small changes to the join table optimizer to make some joins faster.
+@item
+@code{SELECT DISTINCT} is much faster; It uses the new @code{UNIQUE}
+functionality in @code{MyISAM}. One difference compared to @strong{MySQL} 3.22
+is that the output of @code{DISTINCT} is not sorted anymore.
+@item
+All C client API macros are now functions to make shared libraries more
+reliable. Because of this, you can no longer call @code{mysql_num_fields()} on
+a @code{MYSQL} object, you must use @code{mysql_field_count()} instead.
+@item
+Added use of @code{LIBEWRAP}; Patch by Henning P . Schmiedehausen.
+@item
+Don't allow @code{AUTO_INCREMENT} for other than numerical columns.
+@item
+Using @code{AUTO_INCREMENT} will now automatically make the column
+@code{NOT NULL}.
+@item
+Show @code{NULL} as the default value for AUTO_INCREMENT columns.
+@item
+Added @code{SQL_BIG_RESULT}; @code{SQL_SMALL_RESULT} is now default.
+@item
+Added a shared library RPM. This enchancement was contributed by David
+Fox (dsfox@@cogsci.ucsd.edu).
+@item
+Added a @code{--enable-large-files/--disable-large-files} switch to
+@code{configure}. See @file{configure.in} for some systems where this is
+automatically turned off because of broken implementations.
+@item
+Upgraded @code{readline} to 4.0.
+@item
+New @code{CREATE TABLE} options: @code{PACK_KEYS} and @code{CHECKSUM}.
+@item
+Added @code{mysqld} option @code{--default-table-type}.
+@end itemize
+
+@node News-3.22.x, News-3.21.x, News-3.23.x, News
+@appendixsec Changes in release 3.22.x
+
+The 3.22 version has faster and safer connect code and a lot of new nice
+enhancements. The reason for not including these changes in the 3.21 version
+is mainly that we are trying to avoid big changes to 3.21 to keep it as
+stable as possible. As there aren't really any MAJOR changes, upgrading to
+3.22 should be very easy and painless.
+@xref{Upgrading-from-3.21}.
+
+3.22 should also be used with the new @code{DBD-mysql} (1.20xx) driver
+that can use the new connect protocol!
+
+@menu
+* News-3.22.35:: Changes in release 3.22.35
+* News-3.22.34:: Changes in release 3.22.34
+* News-3.22.33:: Changes in release 3.22.33
+* News-3.22.32:: Changes in release 3.22.32
+* News-3.22.31:: Changes in release 3.22.31
+* News-3.22.30:: Changes in release 3.22.30
+* News-3.22.29:: Changes in release 3.22.29
+* News-3.22.28:: Changes in release 3.22.28
+* News-3.22.27:: Changes in release 3.22.27
+* News-3.22.26:: Changes in release 3.22.26
+* News-3.22.25:: Changes in release 3.22.25
+* News-3.22.24:: Changes in release 3.22.24
+* News-3.22.23:: Changes in release 3.22.23
+* News-3.22.22:: Changes in release 3.22.22
+* News-3.22.21:: Changes in release 3.22.21
+* News-3.22.20:: Changes in release 3.22.20
+* News-3.22.19:: Changes in release 3.22.19
+* News-3.22.18:: Changes in release 3.22.18
+* News-3.22.17:: Changes in release 3.22.17
+* News-3.22.16:: Changes in release 3.22.16
+* News-3.22.15:: Changes in release 3.22.15
+* News-3.22.14:: Changes in release 3.22.14
+* News-3.22.13:: Changes in release 3.22.13
+* News-3.22.12:: Changes in release 3.22.12
+* News-3.22.11:: Changes in release 3.22.11
+* News-3.22.10:: Changes in release 3.22.10
+* News-3.22.9:: Changes in release 3.22.9
+* News-3.22.8:: Changes in release 3.22.8
+* News-3.22.7:: Changes in release 3.22.7
+* News-3.22.6:: Changes in release 3.22.6
+* News-3.22.5:: Changes in release 3.22.5
+* News-3.22.4:: Changes in release 3.22.4
+* News-3.22.3:: Changes in release 3.22.3
+* News-3.22.2:: Changes in release 3.22.2
+* News-3.22.1:: Changes in release 3.22.1
+* News-3.22.0:: Changes in release 3.22.0
+@end menu
+
+@node News-3.22.35, News-3.22.34, News-3.22.x, News-3.22.x
+@appendixsubsec Changes in release 3.22.35
+@itemize @bullet
+@item
+Fixed problem with @code{STD()}.
+@item
+Merged changes from the newest @code{ISAM} library from 3.23.
+@item
+Fixed problem with @code{INSERT DELAYED}.
+@item
+Fixed a bug core dump when using a @code{LEFT JOIN}/@code{STRAIGHT_JOIN}
+on a table with only one row.
+@end itemize
+
+@node News-3.22.34, News-3.22.33, News-3.22.35, News-3.22.x
+@appendixsubsec Changes in release 3.22.34
+@itemize @bullet
+@item
+Fixed problem with @code{GROUP BY} on @code{TINYBLOB} columns; This
+caused bugzilla to not show rows in some queries.
+@item
+Had to do total recompile of the Windows binary version as VC++ didn't
+compile all relevant files for 3.22.33 :(
+@end itemize
+
+@node News-3.22.33, News-3.22.32, News-3.22.34, News-3.22.x
+@appendixsubsec Changes in release 3.22.33
+@itemize @bullet
+@item
+Fixed problems in windows when locking tables with @code{LOCK TABLE}
+@item
+Quicker kill of @code{SELECT DISTINCT} queries.
+@end itemize
+
+@node News-3.22.32, News-3.22.31, News-3.22.33, News-3.22.x
+@appendixsubsec Changes in release 3.22.32
+@itemize @bullet
+@item
+Fixed problem when storing numbers in timestamps.
+@item
+Fix problem with timezones that have half hour offsets.
+@item
+@code{mysqlhotcopy} - fast on-line hot-backup utility for local @strong{MySQL}
+databases. By Tim Bunce.
+@item
+New more secure @code{mysqlaccess}. Thanks to Steve Harvey for this.
+@item
+Fixed security problem in the protocol regarding password checking.
+@item
+Fixed problem that affected queries that did arithmetic on @code{GROUP} functions.
+@item
+Fixed a bug in the @code{ISAM} code when deleting rows on tables with
+packed indexes.
+@end itemize
+
+@node News-3.22.31, News-3.22.30, News-3.22.32, News-3.22.x
+@appendixsubsec Changes in release 3.22.31
+
+@itemize @bullet
+@item
+A few small fixes for the Win32 version.
+@end itemize
+
+
+@node News-3.22.30, News-3.22.29, News-3.22.31, News-3.22.x
+@appendixsubsec Changes in release 3.22.30
+
+@itemize @bullet
+@item
+Fixed optimizer problem on @code{SELECT} when using many overlapping indexes.
+@item
+Disabled floating point exceptions for FreeBSD to fix core dump when
+doing @code{SELECT floor(pow(2,63))}.
+@item
+Added print of default arguments options to all clients.
+@item
+Fixed critical problem with the @code{WITH GRANT OPTION} option.
+@item
+Fixed non-critical Y2K problem when writing short date to log files.
+@end itemize
+
+@node News-3.22.29, News-3.22.28, News-3.22.30, News-3.22.x
+@appendixsubsec Changes in release 3.22.29
+
+@itemize @bullet
+@item
+Upgraded the configure and include files to match the latest 3.23 version.
+This should increase portability and make it easier to build shared libraries.
+@item
+Added latest patches to mit-pthreads for NetBSD.
+@item
+Fixed problem with timezones that are < GMT -11.
+@item
+Fixed a bug when deleting packed keys in NISAM.
+@item
+Fixed problem that could cause @strong{MySQL} to touch freed memory when
+doing very complicated @code{GROUP BY} queries.
+@item
+Fixed core dump if you got a crashed table where an @code{ENUM} field value
+was too big.
+@item
+Added @code{mysqlshutdown.exe} and @code{mysqlwatch.exe} to the Windows
+distribution.
+@item
+Fixed problem when doing @code{ORDER BY} on a reference key.
+@item
+Fixed that @code{INSERT DELAYED} doesn't update timestamps that are given.
+
+@end itemize
+
+@node News-3.22.28, News-3.22.27, News-3.22.29, News-3.22.x
+@appendixsubsec Changes in release 3.22.28
+
+@itemize @bullet
+@item
+Fixed problem with @code{LEFT JOIN} and @code{COUNT()} on a column which
+was declared @code{NULL} + and it had a @code{DEFAULT} value.
+@item
+Fixed core dump problem when using @code{CONCAT()} in a @code{WHERE} clause.
+@item
+Fixed problem with @code{AVG()} and @code{STD()} with @code{NULL} values.
+@end itemize
+
+@node News-3.22.27, News-3.22.26, News-3.22.28, News-3.22.x
+@appendixsubsec Changes in release 3.22.27
+
+@itemize @bullet
+@item
+Fixed prototype in @file{my_ctype.h} when using other character sets.
+@item
+Some configure issues to fix problems with big file system detection.
+@item
+Fixed problem when sorting on big blob columns.
+@item
+@code{ROUND()} will now work on Win32.
+@end itemize
+
+@node News-3.22.26, News-3.22.25, News-3.22.27, News-3.22.x
+@appendixsubsec Changes in release 3.22.26
+
+@itemize @bullet
+@item
+Fixed core dump with empty @code{BLOB/TEXT} column to @code{REVERSE()}.
+@item
+Extended @code{/*! */} with version numbers.
+@item
+Changed @code{SUBSTRING(text FROM pos)} to conform to ANSI SQL. (Before this
+construct returned the rightmost 'pos' characters).
+@item
+Fixed problem with @code{LOCK TABLES} combined with @code{DELETE FROM table}
+@item
+Fixed problem that INSERT ... SELECT didn't use SQL_BIG_TABLES.
+@item
+@code{SET SQL_LOW_PRIORITY_UPDATES=#} didn't work.
+@item
+Password wasn't updated correctly if privileges didn't change on:
+@code{GRANT ... IDENTIFIED BY}
+@item
+Fixed range optimizer bug in
+@code{SELECT * FROM table_name WHERE key_part1 >= const AND (key_part2 = const OR key_part2 = const)}
+@item
+Fixed bug in compression key handling in ISAM.
+@end itemize
+
+@node News-3.22.25, News-3.22.24, News-3.22.26, News-3.22.x
+@appendixsubsec Changes in release 3.22.25
+
+@itemize @bullet
+@item
+Fixed some small problems with the installation.
+@end itemize
+
+@node News-3.22.24, News-3.22.23, News-3.22.25, News-3.22.x
+@appendixsubsec Changes in release 3.22.24
+
+@itemize @bullet
+@item
+@code{DATA} is not a reserved word anymore.
+@item
+Fixed optimizer bug with tables with only one row.
+@item
+Fixed bug when using @code{LOCK TABLES table_name READ; FLUSH TABLES;}
+@item
+Applied some patches for HP-UX.
+@item
+@code{isamchk} should now work on Win32.
+@item
+Changed @file{configure} to not use big file handling on Linux as this
+crashes some RedHat 6.0 systems
+@end itemize
+
+@node News-3.22.23, News-3.22.22, News-3.22.24, News-3.22.x
+@appendixsubsec Changes in release 3.22.23
+
+@itemize @bullet
+@item
+Upgraded to use Autoconf 2.13, Automake 1.4 and @code{libtool} 1.3.2.
+@item
+Better support for SCO in @code{configure}.
+@item
+Added option @code{--defaults-file=###} to option file handling to force use
+of only one specific option file.
+@item
+Extended @code{CREATE} syntax to ignore @strong{MySQL} 3.23 keywords.
+@item
+Fixed deadlock problem when using @code{INSERT DELAYED} on a table locked with
+@code{LOCK TABLES}.
+@item
+Fixed deadlock problem when using @code{DROP TABLE} on a table that was
+locked by another thread.
+@item
+Add logging of @code{GRANT/REVOKE} commands in the update log.
+@item
+Fixed @code{isamchk} to detect a new error condition.
+@item
+Fixed bug in @code{NATURAL LEFT JOIN}.
+@end itemize
+
+@node News-3.22.22, News-3.22.21, News-3.22.23, News-3.22.x
+@appendixsubsec Changes in release 3.22.22
+
+@itemize @bullet
+@item
+Fixed problem in the C API when you called @code{mysql_close()} directly after
+@code{mysql_init()}.
+@item
+Better client error message when you can't open socket.
+@item
+Fixed @code{delayed_insert_thread} counting when you couldn't create a new
+delayed_insert thread.
+@item
+Fixed bug in @code{CONCAT()} with many arguments.
+@item
+Added patches for DEC 3.2 and SCO.
+@item
+Fixed path-bug when installing @strong{MySQL} as a service on NT.
+@item
+The @strong{MySQL}-Win32 version is now compiled with VC++ 6.0 instead of
+with VC++ 5.0.
+@item
+New installation setup for @strong{MySQL}-Win32.
+@end itemize
+
+@node News-3.22.21, News-3.22.20, News-3.22.22, News-3.22.x
+@appendixsubsec Changes in release 3.22.21
+
+@itemize @bullet
+@item
+Fixed problem with @code{DELETE FROM TABLE} when table was locked by
+another thread.
+@item
+Fixed bug in @code{LEFT JOIN} involving empty tables.
+@item
+Changed the @code{mysql.db} column from @code{char(32)} to @code{char(60)}.
+@item
+@code{MODIFY} and @code{DELAYED} are not reserved words anymore.
+@item
+Fixed a bug when storing days in a @code{TIME} column.
+@item
+Fixed a problem with @code{Host '..' is not allowed to connect to this MySQL
+server} after one had inserted a new @strong{MySQL} user with a @code{GRANT}
+command.
+@item
+Changed to use @code{TCP_NODELAY} also on Linux (Should give faster TCP/IP
+connections).
+@end itemize
+
+@node News-3.22.20, News-3.22.19, News-3.22.21, News-3.22.x
+@appendixsubsec Changes in release 3.22.20
+
+@itemize @bullet
+@item
+Fixed @code{STD()} for big tables when result should be 0.
+@item
+The update log didn't have newlines on some operating systems.
+@item
+@code{INSERT DELAYED} had some garbage at end in the update log.
+@end itemize
+
+@node News-3.22.19, News-3.22.18, News-3.22.20, News-3.22.x
+@appendixsubsec Changes in release 3.22.19
+
+@itemize @bullet
+@item
+Fixed bug in @code{mysql_install_db} (from 3.22.17).
+@item
+Changed default key cache size to 8M.
+@item
+Fixed problem with queries that needed temporary tables with @code{BLOB}
+columns.
+@end itemize
+
+@node News-3.22.18, News-3.22.17, News-3.22.19, News-3.22.x
+@appendixsubsec Changes in release 3.22.18
+
+@itemize @bullet
+@item
+Fixes a fatal problem in 3.22.17 on Linux; After @code{shutdown}
+all threads didn't die properly.
+@item
+Added option @code{-O flush_time=#} to @code{mysqld}. This is mostly
+useful on Win32 and tells how often @strong{MySQL} should close all
+unused tables and flush all updated tables to disk.
+@item
+Fixed problem that a @code{VARCHAR} column compared with @code{CHAR} column
+didn't use keys efficiently.
+@end itemize
+
+@node News-3.22.17, News-3.22.16, News-3.22.18, News-3.22.x
+@appendixsubsec Changes in release 3.22.17
+
+@itemize @bullet
+@item
+Fixed a core dump problem when using @code{--log-update} and connecting
+without a default database.
+@item
+Fixed some @code{configure} and portability problems.
+@item
+Using @code{LEFT JOIN} on tables that had circular dependencies caused
+@code{mysqld} to hang forever.
+@end itemize
+
+@node News-3.22.16, News-3.22.15, News-3.22.17, News-3.22.x
+@appendixsubsec Changes in release 3.22.16
+
+@itemize @bullet
+@item
+@code{mysqladmin processlist} could kill the server if a new user logged in.
+@item
+@code{DELETE FROM tbl_name WHERE key_column=col_name} didn't find any matching
+rows. Fixed.
+@item
+@code{DATE_ADD(column,...)} didn't work.
+@item
+@code{INSERT DELAYED} could deadlock with status 'upgrading lock'
+@item
+Extended @code{ENCRYPT()} to take longer salt strings than 2 characters.
+@item
+@code{longlong2str} is now much faster than before. For @code{Intel x86}
+platforms, this function is written in optimized assembler.
+@item
+Added the @code{MODIFY} keyword to @code{ALTER TABLE}.
+@end itemize
+
+@node News-3.22.15, News-3.22.14, News-3.22.16, News-3.22.x
+@appendixsubsec Changes in release 3.22.15
+
+@itemize @bullet
+@item
+@code{GRANT} used with @code{IDENTIFIED BY} didn't take effect until privileges
+were flushed.
+@item
+Name change of some variables in @code{SHOW STATUS}.
+@item
+Fixed problem with @code{ORDER BY} with 'only index' optimization when there
+were multiple key definitions for a used column.
+@item
+@code{DATE} and @code{DATETIME} columns are now up to 5 times faster than
+before.
+@item
+@code{INSERT DELAYED} can be used to let the client do other things while the
+server inserts rows into a table.
+@item
+@code{LEFT JOIN USING (col1,col2)} didn't work if one used it with tables
+from 2 different databases.
+@item
+@code{LOAD DATA LOCAL INFILE} didn't work in the Unix version because of
+a missing file.
+@item
+Fixed problems with @code{VARCHAR}/@code{BLOB} on very short rows (< 4 bytes);
+error 127 could occur when deleting rows.
+@item
+Updating @code{BLOB/TEXT} through formulas didn't work for short (< 256 char)
+strings.
+@item
+When you did a @code{GRANT} on a new host, @code{mysqld} could die on the first
+connect from this host.
+@item
+Fixed bug when one used @code{ORDER BY} on column name that was the same
+name as an alias.
+@item
+Added @code{BENCHMARK(loop_count,expression)} function to time expressions.
+@end itemize
+
+@node News-3.22.14, News-3.22.13, News-3.22.15, News-3.22.x
+@appendixsubsec Changes in release 3.22.14
+
+@itemize @bullet
+@item
+Allow empty arguments to @code{mysqld} to make it easier to start from shell
+scripts.
+@item
+Setting a @code{TIMESTAMP} column to @code{NULL} didn't record the timestamp
+value in the update log.
+@item
+Fixed lock handler bug when one did
+@code{INSERT INTO TABLE ... SELECT ... GROUP BY}.
+@item
+Added a patch for @code{localtime_r()} on Win32 so that it will not crash
+anymore if your date is > 2039, but instead will return a time of all zero.
+@item
+Names for
+user-defined functions are no longer case sensitive.
+@item
+Added escape of @code{^Z} (ASCII 26) to @code{\Z} as @code{^Z} doesn't
+work with pipes on Win32.
+@item
+@code{mysql_fix_privileges} adds a new column to the @code{mysql.func} to
+support aggregate UDF functions in future @strong{MySQL} releases.
+@end itemize
+
+@node News-3.22.13, News-3.22.12, News-3.22.14, News-3.22.x
+@appendixsubsec Changes in release 3.22.13
+
+@itemize @bullet
+@item
+Saving @code{NOW()}, @code{CURDATE()} or @code{CURTIME()} directly in a
+column didn't work.
+@item
+@code{SELECT COUNT(*) ... LEFT JOIN ...} didn't work with no @code{WHERE} part.
+@item
+Updated @file{config.guess} to allow @strong{MySQL} to configure on
+UnixWare 7.0.x.
+@item
+Changed the implementation of @code{pthread_cond()} on the Win32 version.
+@code{get_lock()} now correctly times out on Win32!
+@end itemize
+
+@node News-3.22.12, News-3.22.11, News-3.22.13, News-3.22.x
+@appendixsubsec Changes in release 3.22.12
+
+@itemize @bullet
+@item
+Fixed problem when using @code{DATE_ADD()} and @code{DATE_SUB()} in a
+@code{WHERE} clause.
+@item
+You can now set the password for a user with the @code{GRANT ... TO user
+IDENTIFIED BY 'password'} syntax.
+@item
+Fixed bug in @code{GRANT} checking with @code{SELECT} on many tables.
+@item
+Added missing file @code{mysql_fix_privilege_tables} to the RPM
+distribution. This is not run by default because it relies on the client
+package.
+@item
+Added option @code{SQL_SMALL_RESULT} to @code{SELECT} to force use of
+fast temporary tables when you know that the result set will be small.
+@item
+Allow use of negative real numbers without a decimal point.
+@item
+Day number is now adjusted to maximum days in month if the resulting month
+after @code{DATE_ADD}/@code{DATE_SUB()} doesn't have enough days.
+@item
+Fix that @code{GRANT} compares columns in case-insensitive fashion.
+@item
+Fixed a bug in @file{sql_list.h} that made @code{ALTER TABLE} dump core in
+some contexts.
+@item
+The hostname in @code{user@@hostname} can now include @samp{.} and @samp{-}
+without quotes in the context of the @code{GRANT}, @code{REVOKE} and
+@code{SET PASSWORD FOR ...} statements.
+@item
+Fix for @code{isamchk} for tables which need big temporary files.
+@end itemize
+
+@node News-3.22.11, News-3.22.10, News-3.22.12, News-3.22.x
+@appendixsubsec Changes in release 3.22.11
+
+@itemize @bullet
+@item
+@strong{IMPORTANT}: You must run the @code{mysql_fix_privilege_tables} script
+when you upgrade to this version! This is needed because of the new
+@code{GRANT} system. If you don't do this, you will get @code{Access
+denied} when you try to use @code{ALTER TABLE}, @code{CREATE INDEX} or
+@code{DROP INDEX}.
+@item
+@code{GRANT} to allow/deny users table and column access.
+@item
+Changed @code{USER()} to return @code{user@@host}
+@item
+Changed the syntax for how to set @code{PASSWORD} for another user.
+@item
+New command @code{FLUSH STATUS} that sets most status variables to zero.
+@item
+New status variables: @code{aborted_threads}, @code{aborted_connects}.
+@item
+New option variable: @code{connection_timeout}.
+@item
+Added support for Thai sorting (by Pruet Boonma
+@email{pruet@@ds90.intanon.nectec.or.th}).
+@item
+Slovak and japanese error messages.
+@item
+Configuration and portability fixes.
+@item
+Added option @code{SET SQL_WARNINGS=1} to get a warning count also for simple
+inserts.
+@item
+@strong{MySQL} now uses @code{SIGTERM} instead of @code{SIGQUIT} with
+shutdown to work better on FreeBSD.
+@item
+Added option @code{\G} (print vertically) to @code{mysql}.
+@item
+@code{SELECT HIGH_PRIORITY} ... killed @code{mysqld}.
+@item
+@code{IS NULL} on a @code{AUTO_INCREMENT} column in a @code{LEFT JOIN} didn't
+work as expected.
+@item
+New function @code{MAKE_SET()}.
+@end itemize
+
+@node News-3.22.10, News-3.22.9, News-3.22.11, News-3.22.x
+@appendixsubsec Changes in release 3.22.10
+
+@itemize @bullet
+@item
+@code{mysql_install_db} no longer starts the @strong{MySQL} server! You
+should start @code{mysqld} with @code{safe_mysqld} after installing it! The
+@strong{MySQL} RPM will however start the server as before.
+@item
+Added @code{--bootstrap} option to @code{mysqld} and recoded
+@code{mysql_install_db} to use it. This will make it easier to install
+@strong{MySQL} with RPMs.
+@item
+Changed @code{+}, @code{-} (sign and minus), @code{*}, @code{/}, @code{%},
+@code{ABS()} and @code{MOD()} to be @code{BIGINT} aware (64-bit safe).
+@item
+Fixed a bug in @code{ALTER TABLE} that caused @code{mysqld} to crash.
+@item
+@strong{MySQL} now always reports the conflicting key values when a
+duplicate key entry occurs. (Before this was only reported for @code{INSERT}).
+@item
+New syntax: @code{INSERT INTO tbl_name SET col_name=value,col_name=value,...}
+@item
+Most errors in the @file{.err} log are now prefixed with a time stamp.
+@item
+Added option @code{MYSQL_INIT_COMMAND} to @code{mysql_options()} to make
+a query on connect or reconnect.
+@item
+Added option @code{MYSQL_READ_DEFAULT_FILE} and
+@code{MYSQL_READ_DEFAULT_GROUP} to @code{mysql_options()} to read the
+following parameters from the @strong{MySQL} option files: @code{port},
+@code{socket}, @code{compress}, @code{password}, @code{pipe}, @code{timeout},
+@code{user}, @code{init-command}, @code{host} and @code{database}.
+@item
+Added @code{maybe_null} to the UDF structure.
+@item
+Added option @code{IGNORE} to @code{INSERT} statemants with many rows.
+@item
+Fixed some problems with sorting of the koi8 character sets; Users of koi8
+@strong{MUST} run @code{isamchk -rq} on each table that has an index on
+a @code{CHAR} or @code{VARCHAR} column.
+@item
+New script @code{mysql_setpermission}, by Luuk de Boer, allows one
+to easily create new users with permissions for specific databases.
+@item
+Allow use of hexadecimal strings (0x...) when specifying a constant string
+(like in the column separators with @code{LOAD DATA INFILE}).
+@item
+Ported to OS/2 (thanks to Antony T. Curtis @email{antony.curtis@@olcs.net}).
+@item
+Added more variables to @code{SHOW STATUS} and changed format of output to
+be like @code{SHOW VARIABLES}.
+@item
+Added @code{extended-status} command to @code{mysqladmin} which will show the
+new status variables.
+@end itemize
+
+@node News-3.22.9, News-3.22.8, News-3.22.10, News-3.22.x
+@appendixsubsec Changes in release 3.22.9
+
+@itemize @bullet
+@item
+@code{SET SQL_LOG_UPDATE=0} caused a lockup of the server.
+@item
+New SQL command: @code{FLUSH [ TABLES | HOSTS | LOGS | PRIVILEGES ] [, ...]}
+@item
+New SQL command: @code{KILL} @code{thread_id}.
+@item
+Added casts and changed include files to make @strong{MySQL} easier to
+compile on AIX and DEC OSF1 4.x
+@item
+Fixed conversion problem when using @code{ALTER TABLE} from a @code{INT}
+to a short @code{CHAR()} column.
+@item
+Added @code{SELECT HIGH_PRIORITY}; This will get a lock for the
+@code{SELECT} even if there is a thread waiting for another
+@code{SELECT} to get a @code{WRITE LOCK}.
+@item
+Moved wild_compare to string class to be able to use @code{LIKE} on
+@code{BLOB}/@code{TEXT} columns with @code{\0}.
+@item
+Added @code{ESCAPE} option to @code{LIKE}.
+@item
+Added a lot more output to @code{mysqladmin debug}.
+@item
+You can now start @code{mysqld} on Win32 with the @code{--flush} option.
+This will flush all tables to disk after each update. This makes things
+much safer on NT/Win98 but also @strong{MUCH} slower.
+@end itemize
+
+@node News-3.22.8, News-3.22.7, News-3.22.9, News-3.22.x
+@appendixsubsec Changes in release 3.22.8
+
+@itemize @bullet
+@item
+Czech character sets should now work much better. You must also install
+@uref{http://www.mysql.com/Downloads/Patches/czech-3.22.8-patch}.
+This patch should also be installed if you are using a character set with
+uses @code{my_strcoll()}! The patch should always be safe to install (for any system),
+but as this patch changes ISAM internals it's not yet in the default
+distribution.
+@item
+@code{DATE_ADD()} and @code{DATE_SUB()} didn't work with group functions.
+@item
+@code{mysql} will now also try to reconnect on @code{USE DATABASE} commands.
+@item
+Fix problem with @code{ORDER BY} and @code{LEFT JOIN} and @code{const} tables.
+@item
+Fixed problem with @code{ORDER BY} if the first @code{ORDER BY} column
+was a key and the rest of the @code{ORDER BY} columns wasn't part of the key.
+@item
+Fixed a big problem with @code{OPTIMIZE TABLE}.
+@item
+@strong{MySQL} clients on NT will now by default first try to connect with
+named pipes and after this with TCP/IP.
+@item
+Fixed a problem with @code{DROP TABLE} and @code{mysqladmin shutdown} on Win32
+(a fatal bug from 3.22.6).
+@item
+Fixed problems with @code{TIME columns} and negative strings.
+@item
+Added an extra thread signal loop on shutdown to avoid some error messages
+from the client.
+@item
+@strong{MySQL} now uses the next available number as extension for the update
+log file.
+@item
+Added patches for UNIXWARE 7.
+@end itemize
+
+@node News-3.22.7, News-3.22.6, News-3.22.8, News-3.22.x
+@appendixsubsec Changes in release 3.22.7
+
+@itemize @bullet
+@item
+Added @code{LIMIT} clause for the @code{DELETE} statement.
+@item
+You can now use the @code{/*! ... */} syntax to hide @strong{MySQL}-specific
+keywords when you write portable code. @strong{MySQL} will parse the code
+inside the comments as if the surrounding @code{/*!} and @code{*/} comment
+characters didn't exist.
+@item
+@code{OPTIMIZE TABLE tbl_name} can now be used to reclaim disk space
+after many deletes. Currently, this uses @code{ALTER TABLE} to
+re-generate the table, but in the future it will use an integrated
+@code{isamchk} for more speed.
+@item
+Upgraded @code{libtool} to get the configure more portable.
+@item
+Fixed slow @code{UPDATE} and @code{DELETE} operations when using
+@code{DATETIME} or @code{DATE} keys.
+@item
+Changed optimizer to make it better at deciding when to do a full join
+and when using keys.
+@item
+You can now use @code{mysqladmin proc} to display information about your own
+threads. Only users with the @strong{Process_priv} privilege can get
+information about all threads.
+@item
+Added handling of formats @code{YYMMDD}, @code{YYYYMMDD},
+@code{YYMMDDHHMMSS} for numbers when using @code{DATETIME} and
+@code{TIMESTAMP} types. (Formerly these formats only worked with strings.)
+@item
+Added connect option @code{CLIENT_IGNORE_SPACE} to allow use of spaces
+after function names and before @samp{(} (Powerbuilder requires this).
+This will make all function names reserved words.
+@item
+Added the @code{--log-long-format} option to @code{mysqld} to enable timestamps
+and INSERT_ID's in the update log.
+@item
+Added @code{--where} option to @code{mysqldump} (patch by Jim Faucette).
+@item
+The lexical analyzer now uses ``perfect hashing'' for faster parsing of SQL
+statements.
+@end itemize
+
+@node News-3.22.6, News-3.22.5, News-3.22.7, News-3.22.x
+@appendixsubsec Changes in release 3.22.6
+
+@itemize @bullet
+@item
+Faster @code{mysqldump}.
+@item
+For the @code{LOAD DATA INFILE} statement, you can now use the new @code{LOCAL}
+keyword to read the file from the client. @code{mysqlimport} will
+automatically use @code{LOCAL} when importing with the TCP/IP protocol.
+@item
+Fixed small optimize problem when updating keys.
+@item
+Changed makefiles to support shared libraries.
+@item
+@strong{MySQL}-NT can now use named pipes, which means that you can now use
+@strong{MySQL}-NT without having to install TCP/IP.
+@end itemize
+
+@node News-3.22.5, News-3.22.4, News-3.22.6, News-3.22.x
+@appendixsubsec Changes in release 3.22.5
+
+@itemize @bullet
+@item
+All table lock handing is changed to avoid some very subtle
+deadlocks when using @code{DROP TABLE}, @code{ALTER TABLE}, @code{DELETE FROM
+TABLE} and @code{mysqladmin flush-tables} under heavy usage.
+Changed locking code to get better handling of locks of different types.
+@item
+Updated @code{DBI} to 1.00 and @code{DBD} to 1.2.0.
+@item
+Added a check that the error message file contains error messages suitable for
+the current version of @code{mysqld}. (To avoid errors if you accidentally
+try to use an old error message file.)
+@item
+All count structures in the client (@code{affected_rows()},
+@code{insert_id()},...) are now of type @code{BIGINT} to allow 64-bit values
+to be used.
+This required a minor change in the @strong{MySQL} protocol which should affect
+only old clients when using tables with @code{AUTO_INCREMENT} values > 24M.
+@item
+The return type of @code{mysql_fetch_lengths()} has changed from @code{uint *}
+to @code{ulong *}. This may give a warning for old clients but should work
+on most machines.
+@item
+Change @code{mysys} and @code{dbug} libraries to allocate all thread variables
+in one struct. This makes it easier to make a threaded @file{libmysql.dll}
+library.
+@item
+Use the result from @code{gethostname()} (instead of @code{uname()}) when
+constructing @file{.pid} file names.
+@item
+New better compressed server/client protocol.
+@item
+@code{COUNT()}, @code{STD()} and @code{AVG()} are extended to handle more than
+4G rows.
+@item
+You can now store values in the range @code{-838:59:59} <= x <=
+@code{838:59:59} in a @code{TIME} column.
+@item
+@strong{WARNING: INCOMPATIBLE CHANGE!!}
+If you set a @code{TIME} column to too short a value, @strong{MySQL} now
+assumes the value is given as: @code{[[[D ]HH:]MM:]SS} instead of
+@code{HH[:MM[:SS]]}.
+@item
+@code{TIME_TO_SEC()} and @code{SEC_TO_TIME()} can now handle negative times
+and hours up to 32767.
+@item
+Added new option
+@code{SET OPTION SQL_LOG_UPDATE=@{0|1@}} to allow users with
+the @strong{process} privilege to bypass the update log.
+(Modified patch from Sergey A Mukhin @email{violet@@rosnet.net}.)
+@item
+Fixed fatal bug in @code{LPAD()}.
+@item
+Initialize line buffer in @file{mysql.cc} to make @code{BLOB} reading from
+pipes safer.
+@item
+Added @code{-O max_connect_errors=#} option to @code{mysqld}.
+Connect errors are now reset for each correct connection.
+@item
+Increased the default value of @code{max_allowed_packet} to @code{1M} in
+@code{mysqld}.
+@item
+Added @code{--low-priority-updates} option to @code{mysqld}, to give
+table-modifying operations (@code{INSERT}, @code{REPLACE}, @code{UPDATE},
+@code{DELETE}) lower priority than retrievals. You can now use
+@code{@{INSERT | REPLACE | UPDATE | DELETE@} LOW_PRIORITY ...} You can
+also use @code{SET OPTION SQL_LOW_PRIORITY_UPDATES=@{0|1@}} to change
+the priority for one thread. One side effect is that @code{LOW_PRIORITY}
+is now a reserved word. :(
+@item
+Add support for @code{INSERT INTO table ... VALUES(...),(...),(...)},
+to allow inserting multiple rows with a single statement.
+@item
+@code{INSERT INTO tbl_name} is now also cached when used with @code{LOCK TABLES}.
+(Previously only @code{INSERT ... SELECT} and @code{LOAD DATA INFILE} were
+cached.)
+@item
+Allow @code{GROUP BY} functions with @code{HAVING}:
+@example
+mysql> SELECT col FROM table GROUP BY col HAVING COUNT(*)>0;
+@end example
+@item
+@code{mysqld} will now ignore trailing @samp{;} characters in queries. This
+is to make it easier to migrate from some other SQL servers that require the
+trailing @samp{;}.
+@item
+Fix for corrupted fixed-format output generated by @code{SELECT INTO OUTFILE}.
+@item
+@strong{WARNING: INCOMPATIBLE CHANGE!!}
+Added Oracle @code{GREATEST()} and @code{LEAST()} functions. You must now use
+these instead of the @code{MAX()} and @code{MIN()} functions to get the
+largest/smallest value from a list of values. These can now handle @code{REAL},
+@code{BIGINT} and string (@code{CHAR} or @code{VARCHAR}) values.
+@item
+@strong{WARNING: INCOMPATIBLE CHANGE!!}
+@code{DAYOFWEEK()} had offset 0 for Sunday. Changed the offset to 1.
+@item
+Give an error for queries that mix @code{GROUP BY} columns and fields when
+there is no @code{GROUP BY} specification.
+@item
+Added @code{--vertical} option to @code{mysql}, for printing results in
+vertical mode.
+@item
+Index-only optimization; some queries are now resolved using
+only indexes. Until @strong{MySQL} 4.0, this works only for numeric columns.
+@xref{MySQL indexes, , @strong{MySQL} indexes}.
+@item
+Lots of new benchmarks.
+@item
+A new C API chapter and lots of other improvements in the manual.
+@end itemize
+
+@node News-3.22.4, News-3.22.3, News-3.22.5, News-3.22.x
+@appendixsubsec Changes in release 3.22.4
+
+@itemize @bullet
+@item
+Added @code{--tmpdir} option to @code{mysqld}, for specifying the location
+of the temporary file directory.
+@item
+@strong{MySQL} now automatically changes a query from an ODBC client:
+@example
+SELECT ... FROM table WHERE auto_increment_column IS NULL
+@end example
+to:
+@example
+SELECT ... FROM table WHERE auto_increment_column == LAST_INSERT_ID()
+@end example
+This allows some ODBC programs (Delphi, Access) to retrieve the newly
+inserted row to fetch the @code{AUTO_INCREMENT} id.
+@item
+@code{DROP TABLE} now waits for all users to free a table before deleting it.
+@item
+Fixed small memory leak in the new connect protocol.
+@item
+New functions @code{BIN()}, @code{OCT()}, @code{HEX()} and @code{CONV()} for
+converting between different number bases.
+@item
+Added function @code{SUBSTRING()} with 2 arguments.
+@item
+If you created a table with a record length smaller than 5, you couldn't
+delete rows from the table.
+@item
+Added optimization to remove const reference tables from @code{ORDER BY} and
+@code{GROUP BY}.
+@item
+@code{mysqld} now automatically disables system locking on Linux and Win32,
+and for systems that use MIT-pthreads. You can force the use of locking
+with the @code{--enable-locking} option.
+@item
+Added @code{--console} option to @code{mysqld}, to force a console window
+(for error messages) when using Win32.
+@item
+Fixed table locks for Win32.
+@item
+Allow @samp{$} in identifiers.
+@item
+Changed name of user-specific configuration file from @file{my.cnf} to
+@file{.my.cnf} (Unix only).
+@item
+Added @code{DATE_ADD()} and @code{DATE_SUB()} functions.
+@end itemize
+
+@node News-3.22.3, News-3.22.2, News-3.22.4, News-3.22.x
+@appendixsubsec Changes in release 3.22.3
+
+@itemize @bullet
+@item
+Fixed a lock problem (bug in @strong{MySQL} 3.22.1) when closing temporary tables.
+@item
+Added missing @code{mysql_ping()} to the client library.
+@item
+Added @code{--compress} option to all @strong{MySQL} clients.
+@item
+Changed @code{byte} to @code{char} in @file{mysql.h} and @file{mysql_com.h}.
+@end itemize
+
+@node News-3.22.2, News-3.22.1, News-3.22.3, News-3.22.x
+@appendixsubsec Changes in release 3.22.2
+
+@itemize @bullet
+@item
+Searching on multiple constant keys that matched more than 30% of the rows
+didn't always use the best possible key.
+@item
+New functions @code{<<}, @code{>>}, @code{RPAD()} and @code{LPAD()}.
+@item
+You can now save default options (like passwords) in a configuration file
+(@file{my.cnf}).
+@item
+Lots of small changes to get @code{ORDER BY} to work when no records are found
+when using fields that are not in @code{GROUP BY} (@strong{MySQL} extension).
+@item
+Added @code{--chroot} option to @code{mysqld}, to start @code{mysqld} in
+a chroot environment (by Nikki Chumakov @email{nikkic@@cityline.ru}).
+@item
+Trailing spaces are now ignored when comparing case-sensitive strings;
+this should fix some problems with ODBC and flag 512!
+@item
+Fixed a core-dump bug in the range optimizer.
+@item
+Added @code{--one-thread} option to @code{mysqld}, for debugging with
+LinuxThreads (or @code{glibc}). (This replaces the @code{-T32} flag)
+@item
+Added @code{DROP TABLE IF EXISTS} to prevent an error from occurring if the
+table doesn't exist.
+@item
+@code{IF} and @code{EXISTS} are now reserved words (they would have to
+be sooner or later).
+@item
+Added lots of new options to @code{mysqldump}.
+@item
+Server error messages are now in @file{mysqld_error.h}.
+@item
+The server/client protocol now supports compression.
+@item
+All bug fixes from @strong{MySQL} 3.21.32.
+@end itemize
+
+@node News-3.22.1, News-3.22.0, News-3.22.2, News-3.22.x
+@appendixsubsec Changes in release 3.22.1
+
+@itemize @bullet
+@item
+Added new C API function @code{mysql_ping()}.
+@item
+Added new API functions @code{mysql_init()} and @code{mysql_options()}.
+You now MUST call @code{mysql_init()} before you call
+@code{mysql_real_connect()}.
+You don't have to call @code{mysql_init()} if you only use
+@code{mysql_connect()}.
+@item
+Added @code{mysql_options(...,MYSQL_OPT_CONNECT_TIMEOUT,...)} so you can set a
+timeout for connecting to a server.
+@item
+Added @code{--timeout} option to @code{mysqladmin}, as a test of
+@code{mysql_options()}.
+@item
+Added @code{AFTER column} and @code{FIRST} options to
+@code{ALTER TABLE ... ADD columns}.
+This makes it possible to add a new column at some specific location
+within a row in an existing table.
+@item
+@code{WEEK()} now takes an optional argument to allow handling of weeks when
+the week starts on Monday (some European countries). By default,
+@code{WEEK()} assumes the week starts on Sunday.
+@item
+@code{TIME} columns weren't stored properly (bug in @strong{MySQL} 3.22.0).
+@item
+@code{UPDATE} now returns information about how many rows were
+matched and updated, and how many ``warnings'' occurred when doing the update.
+@item
+Fixed incorrect result from @code{FORMAT(-100,2)}.
+@item
+@code{ENUM} and @code{SET} columns were compared in binary (case-sensitive)
+fashion; changed to be case insensitive.
+@end itemize
+
+@node News-3.22.0, , News-3.22.1, News-3.22.x
+@appendixsubsec Changes in release 3.22.0
+
+@itemize @bullet
+@item
+New (backward compatible) connect protocol that allows you to
+specify the database to use when connecting, to get much faster
+connections to a specific database.
+
+The @code{mysql_real_connect()} call is changed to:
+
+@example
+mysql_real_connect(MYSQL *mysql, const char *host, const char *user,
+ const char *passwd, const char *db, uint port,
+ const char *unix_socket, uint client_flag)
+@end example
+@item
+Each connection is handled by its own thread, rather than by the
+master @code{accept()} thread. This fixes permanently the telnet bug
+that was a topic on the mail list some time ago.
+@item
+All TCP/IP connections are now checked with backward resolution of
+the hostname to get better security. @code{mysqld} now has a local hostname
+resolver cache so connections should actually be faster than before,
+even with this feature.
+@item
+A site automatically will be blocked from future connections if someone
+repeatedly connects with an ``improper header'' (like when one uses telnet).
+@item
+You can now refer to tables in different databases with references of the form
+@code{tbl_name@@db_name} or @code{db_name.tbl_name}. This makes it possible to
+give a user read access to some tables and write access to others simply by
+keeping them in different databases!
+@item
+Added @code{--user} option to @code{mysqld}, to allow it to run
+as another Unix user (if it is started as the Unix @code{root} user).
+@item
+Added caching of users and access rights (for faster access rights checking)
+@item
+Normal users (not anonymous ones) can change their password with
+@code{mysqladmin password 'new_password'}. This uses encrypted passwords
+that are not logged in the normal @strong{MySQL} log!
+@item
+All important string functions are now coded in assembler for x86 Linux
+machines. This gives a speedup of 10% in many cases.
+@item
+For tables that have many columns, the column names are now hashed for
+much faster column name lookup (this will speed up some benchmark
+tests a lot!)
+@item
+Some benchmarks are changed to get better individual timing.
+(Some loops were so short that a specific test took < 2 seconds. The
+loops have been changed to take about 20 seconds to make it easier
+to compare different databases. A test that took 1-2 seconds before
+now takes 11-24 seconds, which is much better)
+@item
+Re-arranged @code{SELECT} code to handle some very specific queries
+involving group functions (like @code{COUNT(*)}) without a @code{GROUP BY} but
+with @code{HAVING}. The following now works:
+@example
+mysql> SELECT count(*) as C FROM table HAVING C > 1;
+@end example
+@item
+Changed the protocol for field functions to be faster and avoid some
+calls to @code{malloc()}.
+@item
+Added @code{-T32} option to @code{mysqld}, for running all queries under the
+main thread. This makes it possible to debug @code{mysqld} under Linux with
+@code{gdb}!
+@item
+Added optimization of @code{not_null_column IS NULL} (needed for some Access
+queries).
+@item
+Allow @code{STRAIGHT_JOIN} to be used between two tables to force the optimizer
+to join them in a specific order.
+@item
+String functions now return @code{VARCHAR} rather than @code{CHAR} and
+the column type is now @code{VARCHAR} for fields saved as @code{VARCHAR}.
+This should make the @strong{MyODBC} driver better, but may break some old
+@strong{MySQL} clients that don't handle @code{FIELD_TYPE_VARCHAR} the same
+way as @code{FIELD_TYPE_CHAR}.
+@item
+@code{CREATE INDEX} and @code{DROP INDEX} are now implemented through
+@code{ALTER TABLE}.
+@code{CREATE TABLE} is still the recommended (fast) way to create indexes.
+@item
+Added @code{--set-variable} option @code{wait_timeout} to @code{mysqld}.
+@item
+Added time column to @code{mysqladmin processlist} to show how long a query
+has taken or how long a thread has slept.
+@item
+Added lots of new variables to @code{show variables} and some new to
+@code{show status}.
+@item
+Added new type @code{YEAR}. @code{YEAR} is stored in 1 byte with allowable
+values of 0, and 1901 to 2155.
+@item
+Added new @code{DATE} type that is stored in 3 bytes rather than 4 bytes.
+All new tables are created with the new date type if you don't use the
+@code{--old-protocol} option to @code{mysqld}.
+@item
+Fixed bug in record caches; for some queries, you could get
+@code{Error from table handler: #} on some operating systems.
+@item
+Added @code{--enable-assembler} option to @code{configure}, for x86 machines
+(tested on Linux + @code{gcc}). This will enable assembler functions for the
+most important string functions for more speed!
+@end itemize
+
+@node News-3.21.x, News-3.20.x, News-3.22.x, News
+@appendixsec Changes in release 3.21.x
+
+@menu
+* News-3.21.33:: Changes in release 3.21.33
+* News-3.21.32:: Changes in release 3.21.32
+* News-3.21.31:: Changes in release 3.21.31
+* News-3.21.30:: Changes in release 3.21.30
+* News-3.21.29:: Changes in release 3.21.29
+* News-3.21.28:: Changes in release 3.21.28
+* News-3.21.27:: Changes in release 3.21.27
+* News-3.21.26:: Changes in release 3.21.26
+* News-3.21.25:: Changes in release 3.21.25
+* News-3.21.24:: Changes in release 3.21.24
+* News-3.21.23:: Changes in release 3.21.23
+* News-3.21.22:: Changes in release 3.21.22
+* News-3.21.21a:: Changes in release 3.21.21a
+* News-3.21.21:: Changes in release 3.21.21
+* News-3.21.20:: Changes in release 3.21.20
+* News-3.21.19:: Changes in release 3.21.19
+* News-3.21.18:: Changes in release 3.21.18
+* News-3.21.17:: Changes in release 3.21.17
+* News-3.21.16:: Changes in release 3.21.16
+* News-3.21.15:: Changes in release 3.21.15
+* News-3.21.14b:: Changes in release 3.21.14b
+* News-3.21.14a:: Changes in release 3.21.14a
+* News-3.21.13:: Changes in release 3.21.13
+* News-3.21.12:: Changes in release 3.21.12
+* News-3.21.11:: Changes in release 3.21.11
+* News-3.21.10:: Changes in release 3.21.10
+* News-3.21.9:: Changes in release 3.21.9
+* News-3.21.8:: Changes in release 3.21.8
+* News-3.21.7:: Changes in release 3.21.7
+* News-3.21.6:: Changes in release 3.21.6
+* News-3.21.5:: Changes in release 3.21.5
+* News-3.21.4:: Changes in release 3.21.4
+* News-3.21.3:: Changes in release 3.21.3
+* News-3.21.2:: Changes in release 3.21.2
+* News-3.21.0:: Changes in release 3.21.0
+@end menu
+
+@node News-3.21.33, News-3.21.32, News-3.21.x, News-3.21.x
+@appendixsubsec Changes in release 3.21.33
+
+@itemize @bullet
+@item
+Fixed problem when sending @code{SIGHUP} to @code{mysqld};
+@code{mysqld} core dumped when starting from boot on some systems.
+@item
+Fixed problem with losing a little memory for some connections.
+@item
+@code{DELETE FROM tbl_name} without a @code{WHERE} condition is now done the
+long way when you use @code{LOCK TABLES} or if the table is in use, to
+avoid race conditions.
+@item
+@code{INSERT INTO TABLE (timestamp_column) VALUES (NULL);} didn't set timestamp.
+@end itemize
+
+@node News-3.21.32, News-3.21.31, News-3.21.33, News-3.21.x
+@appendixsubsec Changes in release 3.21.32
+
+@itemize @bullet
+@item
+Fixed some possible race conditions when doing many reopen/close on the same
+tables under heavy load! This can happen if you execute @code{mysqladmin
+refresh} often. This could in some very rare cases corrupt the header of the
+index file and cause error 126 or 138.
+
+@item
+Fixed fatal bug in @code{refresh()} when running with the
+@code{--skip-locking} option. There was a ``very small'' time gap after
+a @code{mysqladmin refresh} when a table could be corrupted if one
+thread updated a table while another thread did @code{mysqladmin
+refresh} and another thread started a new update ont the same table
+before the first thread had finished. A refresh (or
+@code{--flush-tables}) will now not return until all used tables are
+closed!
+@item
+@code{SELECT DISTINCT} with a @code{WHERE} clause that didn't match any rows
+returned a row in some contexts (bug only in 3.21.31).
+@item
+@code{GROUP BY} + @code{ORDER BY} returned one empty row when no rows where
+found.
+@item
+Fixed a bug in the range optimizer that wrote
+@code{Use_count: Wrong count for ...} in the error log file.
+@end itemize
+
+@node News-3.21.31, News-3.21.30, News-3.21.32, News-3.21.x
+@appendixsubsec Changes in release 3.21.31
+@itemize @bullet
+@item
+Fixed a sign extension problem for the @code{TINYINT} type on Irix.
+@item
+Fixed problem with @code{LEFT("constant_string",function)}.
+@item
+Fixed problem with @code{FIND_IN_SET()}.
+@item
+@code{LEFT JOIN} core dumped if the second table is used with a constant
+@code{WHERE/ON} expression that uniquely identifies one record.
+@item
+Fixed problems with @code{DATE_FORMAT()} and incorrect dates.
+@code{DATE_FORMAT()} now ignores @code{'%'} to make it possible to extend
+it more easily in the future.
+@end itemize
+
+@node News-3.21.30, News-3.21.29, News-3.21.31, News-3.21.x
+@appendixsubsec Changes in release 3.21.30
+@itemize @bullet
+@item
+@code{mysql} now returns an exit code > 0 if the query returned an error.
+@item
+Saving of command line history to file in @code{mysql} client.
+By Tommy Larsen @email{tommy@@mix.hive.no}.
+@item
+Fixed problem with empty lines that were ignored in @file{mysql.cc}.
+@item
+Save the pid of the signal handler thread in the pid file instead
+of the pid of the main thread.
+@item
+Added patch by @email{tommy@@valley.ne.jp} to support Japanese characters
+SJIS and UJIS.
+@item
+Changed @code{safe_mysqld} to redirect startup messages to
+@code{'hostname'.err} instead
+of @code{'hostname'.log} to reclaim file space on @code{mysqladmin refresh}.
+@item
+@code{ENUM} always had the first entry as default value.
+@item
+@code{ALTER TABLE} wrote two entries to the update log.
+@item
+@code{sql_acc()} now closes the @code{mysql} grant tables after a reload to
+save table space and memory.
+@item
+Changed @code{LOAD DATA} to use less memory with tables and @code{BLOB}
+columns.
+@item
+Sorting on a function which made a division / 0 produced a wrong set
+in some cases.
+@item
+Fixed @code{SELECT} problem with @code{LEFT()} when using the czech character
+set.
+@item
+Fixed problem in @code{isamchk}; it couldn't repair a packed table in a very
+unusual case.
+@item
+@code{SELECT} statements with @code{&} or @code{|} (bit functions) failed on
+columns with @code{NULL} values.
+@item
+When comparing a field = field, where one of the fields was a part key,
+only the length of the part key was compared.
+@end itemize
+
+@node News-3.21.29, News-3.21.28, News-3.21.30, News-3.21.x
+@appendixsubsec Changes in release 3.21.29
+@itemize @bullet
+@item
+@code{LOCK TABLES} + @code{DELETE from tbl_name} never removed locks properly.
+@item
+Fixed problem when grouping on an @code{OR} function.
+@item
+Fixed permission problem with @code{umask()} and creating new databases.
+@item
+Fixed permission problem on result file with @code{SELECT ... INTO OUTFILE ...}
+@item
+Fixed problem in range optimizer (core dump) for a very complex query.
+@item
+Fixed problem when using @code{MIN(integer)} or @code{MAX(integer)} in
+@code{GROUP BY}.
+@item
+Fixed bug on Alpha when using integer keys. (Other keys worked on Alpha).
+@item
+Fixed bug in @code{WEEK("XXXX-xx-01")}.
+@end itemize
+
+@node News-3.21.28, News-3.21.27, News-3.21.29, News-3.21.x
+@appendixsubsec Changes in release 3.21.28
+@itemize @bullet
+@item
+Fixed socket permission (clients couldn't connect to Unix socket on Linux).
+@item
+Fixed bug in record caches; for some queries, you could get
+@code{Error from table handler: #} on some operating systems.
+@end itemize
+
+@node News-3.21.27, News-3.21.26, News-3.21.28, News-3.21.x
+@appendixsubsec Changes in release 3.21.27
+@itemize @bullet
+@item
+Added user level lock functions @code{GET_LOCK(string,timeout)},
+@code{RELEASE_LOCK(string)}.
+@item
+Added @code{opened_tables} to @code{show status}.
+@item
+Changed connect timeout to 3 seconds to make it somewhat harder
+for crackers to kill @code{mysqld} through telnet + TCP/IP.
+@item
+Fixed bug in range optimizer when using
+@code{WHERE key_part_1 >= something AND key_part_2 <= something_else}.
+@item
+Changed @code{configure} for detection of FreeBSD 3.0 9803xx and above
+@item
+@code{WHERE} with string_column_key = constant_string didn't always find
+all rows if the column had many values differing only with characters of
+the same sort value (like e and @'e).
+@item
+Strings keys looked up with 'ref' were not compared in case-sensitive fashion.
+@item
+Added @code{umask()} to make log files non-readable for normal users.
+@item
+Ignore users with old (8-byte) password on startup if not using
+@code{--old-protocol} option to @code{mysqld}.
+@item
+@code{SELECT} which matched all key fields returned the values in the
+case of the matched values, not of the found values. (Minor problem.)
+@end itemize
+
+@node News-3.21.26, News-3.21.25, News-3.21.27, News-3.21.x
+@appendixsubsec Changes in release 3.21.26
+@itemize @bullet
+@item
+@code{FROM_DAYS(0)} now returns "0000-00-00".
+@item
+In @code{DATE_FORMAT()}, PM and AM were swapped for hours 00 and 12.
+@item
+Extended the default maximum key size to 256.
+@item
+Fixed bug when using @code{BLOB}/@code{TEXT} in @code{GROUP BY} with many
+tables.
+@item
+An @code{ENUM} field that is not declared @code{NOT NULL} has @code{NULL} as
+the default value.
+(Previously, the default value was the first enumeration value.)
+@item
+Fixed bug in the join optimizer code when using many part keys
+on the same key: @code{INDEX (Organization,Surname(35),Initials(35))}.
+@item
+Added some tests to the table order optimizer to get some cases with
+@code{SELECT ... FROM many_tables} much faster.
+@item
+Added a retry loop around @code{accept()} to possibly fix some problems on some
+Linux machines.
+@end itemize
+
+@node News-3.21.25, News-3.21.24, News-3.21.26, News-3.21.x
+@appendixsubsec Changes in release 3.21.25
+@itemize @bullet
+@item
+Changed @code{typedef 'string'} to @code{typedef 'my_string'} for better
+portability.
+@item
+You can now kill threads that are waiting on a disk full condition.
+@item
+Fixed some problems with UDF functions.
+@item
+Added long options to @code{isamchk}. Try @code{isamchk --help}.
+@item
+Fixed a bug when using 8 bytes long (alpha); @code{filesort()} didn't work.
+Affects @code{DISTINCT}, @code{ORDER BY} and @code{GROUP BY} on 64-bit
+processors.
+@end itemize
+
+@node News-3.21.24, News-3.21.23, News-3.21.25, News-3.21.x
+@appendixsubsec Changes in release 3.21.24
+@itemize @bullet
+@item
+Dynamic loadable functions. Based on source from Alexis Mikhailov.
+@item
+You couldn't delete from a table if no one had done a @code{SELECT} on the
+table.
+@item
+Fixed problem with range optimizer with many @code{OR} operators on key parts
+inside each other.
+@item
+Recoded @code{MIN()} and @code{MAX()} to work properly with strings and
+@code{HAVING}.
+@item
+Changed default umask value for new files from @code{0664} to @code{0660}.
+@item
+Fixed problem with @code{LEFT JOIN} and constant expressions in the @code{ON}
+part.
+@item
+Added Italian error messages from @email{brenno@@dewinter.com}.
+@item
+@code{configure} now works better on OSF1 (tested on 4.0D).
+@item
+Added hooks to allow @code{LIKE} optimization with international character
+support.
+@item
+Upgraded @code{DBI} to 0.93.
+@end itemize
+
+@node News-3.21.23, News-3.21.22, News-3.21.24, News-3.21.x
+@appendixsubsec Changes in release 3.21.23
+@itemize @bullet
+@item
+The following symbols are now reserved words:
+@code{TIME}, @code{DATE}, @code{TIMESTAMP}, @code{TEXT}, @code{BIT},
+@code{ENUM}, @code{NO}, @code{ACTION}, @code{CHECK}, @code{YEAR},
+@code{MONTH}, @code{DAY}, @code{HOUR}, @code{MINUTE}, @code{SECOND},
+@code{STATUS}, @code{VARIABLES}.
+@item
+Setting a @code{TIMESTAMP} to @code{NULL} in @code{LOAD DATA INFILE ...} didn't
+set the current time for the @code{TIMESTAMP}.
+@item
+Fix @code{BETWEEN} to recognize binary strings. Now @code{BETWEEN} is
+case sensitive.
+@item
+Added @code{--skip-thread-priority} option to @code{mysqld}, for systems
+where @code{mysqld}'s thread scheduling doesn't work properly (BSDI 3.1).
+@item
+Added ODBC functions @code{DAYNAME()} and @code{MONTHNAME()}.
+@item
+Added function @code{TIME_FORMAT()}. This works like @code{DATE_FORMAT()},
+but takes a time string (@code{'HH:MM:DD'}) as argument.
+@item
+Fixed unlikely(?) key optimizer bug when using @code{OR}s of key parts
+inside @code{AND}s.
+@item
+Added command @code{variables} to @code{mysqladmin}.
+@item
+A lot of small changes to the binary releases.
+@item
+Fixed a bug in the new protocol from @strong{MySQL} 3.21.20.
+@item
+Changed @code{ALTER TABLE} to work with Win32 (Win32 can't rename open files).
+Also fixed a couple of small bugs in the Win32 version.
+@item
+All standard @strong{MySQL} clients are now ported to @strong{MySQL}-Win32.
+@item
+@strong{MySQL} can now be started as a service on NT.
+@end itemize
+
+@node News-3.21.22, News-3.21.21a, News-3.21.23, News-3.21.x
+@appendixsubsec Changes in release 3.21.22
+@itemize @bullet
+@item
+Starting with this version, all @strong{MySQL} distributions will be
+configured, compiled and tested with @code{crash-me} and the benchmarks on
+the following platforms: SunOS 5.6 sun4u, SunOS 5.5.1 sun4u, SunOS 4.14 sun4c,
+SunOS 5.6 i86pc, Irix 6.3 mips5k, HP-UX 10.20 hppa, AIX 4.2.1 ppc,
+OSF1 V4.0 alpha, FreeBSD 2.2.2 i86pc and BSDI 3.1 i386.
+@item
+Fix @code{COUNT(*)} problems when the @code{WHERE} clause didn't match any
+records. (Bug from 3.21.17.)
+@item
+Removed that @code{NULL = NULL} is true. Now you must use @code{IS NULL}
+or @code{IS NOT NULL} to test whether or not a value is @code{NULL}.
+(This is according to ANSI SQL but may break
+old applications that are ported from @code{mSQL}.)
+You can get the old behavior by compiling with @code{-DmSQL_COMPLIANT}.
+@item
+Fixed bug that core dumped when using many @code{LEFT OUTER JOIN} clauses.
+@item
+Fixed bug in @code{ORDER BY} on string formula with possible @code{NULL} values.
+@item
+Fixed problem in range optimizer when using <= on sub index.
+@item
+Added functions @code{DAYOFYEAR()}, @code{DAYOFMONTH()}, @code{MONTH()},
+@code{YEAR()}, @code{WEEK()}, @code{QUARTER()}, @code{HOUR()}, @code{MINUTE()},
+@code{SECOND()} and @code{FIND_IN_SET()}.
+@item
+Added command @code{SHOW VARIABLES}.
+@item
+Added support of ``long constant strings'' from ANSI SQL:
+@example
+mysql> SELECT 'first ' 'second'; -> 'first second'
+@end example
+@item
+Upgraded mSQL-Mysql-modules to 1.1825.
+@item
+Upgraded @code{mysqlaccess} to 2.02.
+@item
+Fixed problem with Russian character set and @code{LIKE}.
+@item
+Ported to OpenBSD 2.1.
+@item
+New Dutch error messages.
+@end itemize
+
+@node News-3.21.21a, News-3.21.21, News-3.21.22, News-3.21.x
+@appendixsubsec Changes in release 3.21.21a
+@itemize @bullet
+@item
+Configure changes for some operating systems.
+@end itemize
+
+@node News-3.21.21, News-3.21.20, News-3.21.21a, News-3.21.x
+@appendixsubsec Changes in release 3.21.21
+@itemize @bullet
+@item
+Fixed optimizer bug when using
+@code{WHERE data_field = date_field2 AND date_field2 = constant}.
+@item
+Added command @code{SHOW STATUS}.
+@item
+Removed @file{manual.ps} from the source distribution to make it smaller.
+@end itemize
+
+@node News-3.21.20, News-3.21.19, News-3.21.21, News-3.21.x
+@appendixsubsec Changes in release 3.21.20
+@itemize @bullet
+@item
+Changed the maximum table name and column name lengths from 32 to 64.
+@item
+Aliases can now be of ``any'' length.
+@item
+Fixed @code{mysqladmin stat} to return the right number of queries.
+@item
+Changed protocol (downward compatible) to mark if a column has the
+@code{AUTO_INCREMENT} attribute or is a @code{TIMESTAMP}. This is needed for
+the new Java driver.
+@item
+Added Hebrew sorting order by Zeev Suraski.
+@item
+Solaris 2.6: Fixed @code{configure} bugs and increased maximum table size
+from 2G to 4G.
+@end itemize
+
+@node News-3.21.19, News-3.21.18, News-3.21.20, News-3.21.x
+@appendixsubsec Changes in release 3.21.19
+@itemize @bullet
+@item
+Upgraded @code{DBD} to 1823. This version implements @code{mysql_use_result} in
+@code{DBD-Mysql}.
+@item
+Benchmarks updated for empress (by Luuk).
+@item
+Fixed a case of slow range searching.
+@item
+Configure fixes (@file{Docs} directory).
+@item
+Added function @code{REVERSE()} (by Zeev Suraski).
+@end itemize
+
+@node News-3.21.18, News-3.21.17, News-3.21.19, News-3.21.x
+@appendixsubsec Changes in release 3.21.18
+@itemize @bullet
+@item
+Issue error message if client C functions are called in wrong order.
+@item
+Added automatic reconnect to the @file{libmysql.c} library. If a write command
+fails, an automatic reconnect is done.
+@item
+Small sort sets no longer use temporary files.
+@item
+Upgraded @code{DBI} to 0.91.
+@item
+Fixed a couple of problems with @code{LEFT OUTER JOIN}.
+@item
+Added @code{CROSS JOIN} syntax. @code{CROSS} is now a reserved word.
+@item
+Recoded @code{yacc}/@code{bison} stack allocation to be even safer and to allow
+@strong{MySQL} to handle even bigger expressions.
+@item
+Fixed a couple of problems with the update log.
+@item
+@code{ORDER BY} was slow when used with key ranges.
+@end itemize
+
+@node News-3.21.17, News-3.21.16, News-3.21.18, News-3.21.x
+@appendixsubsec Changes in release 3.21.17
+@itemize @bullet
+@item
+Changed documentation string of @code{--with-unix-socket-path} to avoid
+confusion.
+@item
+Added ODBC and ANSI SQL style @code{LEFT OUTER JOIN}.
+@item
+The following are new reserved words: @code{LEFT}, @code{NATURAL},
+@code{USING}.
+@item
+The client library now uses the value of the environment variable
+@code{MYSQL_HOST} as the default host if it's defined.
+@item
+@code{SELECT col_name, SUM(expr)} now returns @code{NULL} for @code{col_name}
+when there are matching rows.
+@item
+Fixed problem with comparing binary strings and @code{BLOB}s with ASCII
+characters over 127.
+@item
+Fixed lock problem: when freeing a read lock on a table with multiple
+read locks, a thread waiting for a write lock would have been given the lock.
+This shouldn't affect data integrity, but could possibly make @code{mysqld}
+restart if one thread was reading data that another thread modified.
+@item
+@code{LIMIT offset,count} didn't work in @code{INSERT ... SELECT}.
+@item
+Optimized key block caching. This will be quicker than the old algorithm when
+using bigger key caches.
+@end itemize
+
+@node News-3.21.16, News-3.21.15, News-3.21.17, News-3.21.x
+@appendixsubsec Changes in release 3.21.16
+
+@itemize @bullet
+@item
+Added ODBC 2.0 & 3.0 functions @code{POWER()}, @code{SPACE()},
+@code{COT()}, @code{DEGREES()}, @code{RADIANS()}, @code{ROUND(2 arg)}
+and @code{TRUNCATE()}.
+@item
+@strong{WARNING: INCOMPATIBLE CHANGE!!} @code{LOCATE()} parameters were
+swapped according to ODBC standard. Fixed.
+@item
+Added function @code{TIME_TO_SEC()}.
+@item
+In some cases, default values were not used for @code{NOT NULL} fields.
+@item
+Timestamp wasn't always updated properly in @code{UPDATE SET ...} statements.
+@item
+Allow empty strings as default values for @code{BLOB} and @code{TEXT}, to
+be compatible with @code{mysqldump}.
+@end itemize
+
+@node News-3.21.15, News-3.21.14b, News-3.21.16, News-3.21.x
+@appendixsubsec Changes in release 3.21.15
+
+@itemize @bullet
+@item
+@strong{WARNING: INCOMPATIBLE CHANGE!!} @code{mysqlperl} is now from
+Msql-Mysql-modules. This means that @code{connect()} now takes
+@code{host}, @code{database}, @code{user}, @code{password} arguments! The old
+version took @code{host}, @code{database}, @code{password}, @code{user}.
+@item
+Allow @code{DATE '1997-01-01'}, @code{TIME '12:10:10'} and
+@code{TIMESTAMP '1997-01-01 12:10:10'} formats required by ANSI SQL.
+@strong{WARNING: INCOMPATIBLE CHANGE!!} This has the unfortunate
+side-effect that you no longer can have columns named @code{DATE}, @code{TIME}
+or @code{TIMESTAMP}. :( Old columns can still be accessed through
+@code{tablename.columnname}!)
+@item
+Changed Makefiles to hopefully work better with BSD systems. Also,
+@file{manual.dvi} is now included in the distribution to avoid having stupid
+@code{make} programs trying to rebuild it.
+@item
+@code{readline} library upgraded to version 2.1.
+@item
+A new sortorder german-1. That is a normal ISO-Latin1 with a german sort
+order.
+@item
+Perl @code{DBI}/@code{DBD} is now included in the distribution. @code{DBI}
+is now the recommended way to connect to @strong{MySQL} from Perl.
+@item
+New portable benchmark suite with @code{DBD}, with test results from
+@code{mSQL} 2.0.3, @strong{MySQL}, PostgreSQL 6.2.1 and Solid server 2.2.
+@item
+@code{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
+@code{mSQL}, PostgreSQL, Solid and @strong{MySQL}.
+@item
+Fixed bug in range-optimizer that crashed @strong{MySQL} on some queries.
+@item
+Table and column name completion for @code{mysql} command line tool, by Zeev
+Suraski and Andi Gutmans.
+@item
+Added new command @code{REPLACE} that works like @code{INSERT} but
+replaces conflicting records with the new record. @code{REPLACE INTO
+TABLE ... SELECT ...} works also.
+@item
+Added new commands @code{CREATE DATABASE db_name} and @code{DROP
+DATABASE db_name}.
+@item
+Added @code{RENAME} option to @code{ALTER TABLE}: @code{ALTER TABLE name
+RENAME AS new_name}.
+@item
+@code{make_binary_distribution} now includes @file{libgcc.a} in
+@file{libmysqlclient.a}. This should make linking work for people who don't
+have @code{gcc}.
+@item
+Changed @code{net_write()} to @code{my_net_write()} because of a name
+conflict with Sybase.
+@item
+@cindex ODBC compatibility
+@cindex Compatibility, with ODBC
+New function @code{DAYOFWEEK()} compatible with ODBC.
+@item
+Stack checking and @code{bison} memory overrun checking to make @strong{MySQL}
+safer with weird queries.
+@end itemize
+
+@node News-3.21.14b, News-3.21.14a, News-3.21.15, News-3.21.x
+@appendixsubsec Changes in release 3.21.14b
+
+@itemize @bullet
+@item
+Fixed a couple of small @code{configure} problems on some platforms.
+@end itemize
+
+@node News-3.21.14a, News-3.21.13, News-3.21.14b, News-3.21.x
+@appendixsubsec Changes in release 3.21.14a
+
+@itemize @bullet
+@item
+Ported to SCO Openserver 5.0.4 with FSU Pthreads.
+@item
+HP-UX 10.20 should work.
+@item
+Added new function @code{DATE_FORMAT()}.
+@item
+Added @code{NOT IN}.
+@item
+Added automatic removal of 'ODBC function conversions': @code{@{fn now() @}}
+@item
+Handle ODBC 2.50.3 option flags.
+@item
+Fixed comparison of @code{DATE} and @code{TIME} values with @code{NULL}.
+@item
+Changed language name from germany to german to be consistent with
+the other language names.
+@item
+Fixed sorting problem on functions returning a @code{FLOAT}. Previously, the
+values were converted to @code{INT}s before sorting.
+@item
+Fixed slow sorting when sorting on key field when using
+@code{key_column=constant}.
+@item
+Sorting on calculated @code{DOUBLE} values sorted on integer results instead.
+@item
+@code{mysql} no longer needs a database argument.
+@item
+Changed the place where @code{HAVING} should be. According to ANSI, it should
+be after @code{GROUP BY} but before @code{ORDER BY}. @strong{MySQL} 3.20
+incorrectly had it last.
+@item
+Added Sybase command @code{USE DATABASE} to start using another database.
+@item
+Added automatic adjusting of number of connections and table cache size
+if the maximum number of files that can be opened is less than needed.
+This should fix that @code{mysqld} doesn't crash even if you haven't done a
+@code{ulimit -n 256} before starting @code{mysqld}.
+@item
+Added lots of limit checks to make it safer when running with too little
+memory or when doing weird queries.
+@end itemize
+
+@node News-3.21.13, News-3.21.12, News-3.21.14a, News-3.21.x
+@appendixsubsec Changes in release 3.21.13
+
+@itemize @bullet
+@item
+Added retry of interrupted reads and clearing of @code{errno}.
+This makes Linux systems much safer!
+@item
+Fixed locking bug when using many aliases on the same table in the same
+@code{SELECT}.
+@item
+Fixed bug with @code{LIKE} on number key.
+@item
+New error message so you can check whether the connection was lost while
+the command was running or whether the connection was down from the start.
+@item
+Added @code{--table} option to @code{mysql} to print in table format.
+Moved time and row information after query result.
+Added automatic reconnect of lost connections.
+@item
+Added @code{!=} as a synonym for @code{<>}.
+@item
+Added function @code{VERSION()} to make easier logs.
+@item
+New multi-user test @file{tests/fork_test.pl} to put some strain on the
+thread library.
+@end itemize
+
+@node News-3.21.12, News-3.21.11, News-3.21.13, News-3.21.x
+@appendixsubsec Changes in release 3.21.12
+
+@itemize @bullet
+@item
+Fixed @code{ftruncate()} call in MIT-pthreads. This made @code{isamchk}
+destroy the @file{.ISM} files on (Free)BSD 2.x systems.
+@item
+Fixed broken @code{__P_} patch in MIT-pthreads.
+@item
+Many memory overrun checks. All string functions now return @code{NULL}
+if the returned string should be longer than @code{max_allowed_packet} bytes.
+@item
+Changed the name of the @code{INTERVAL} type to @code{ENUM}, because
+@code{INTERVAL} is used in ANSI SQL.
+@item
+In some cases, doing a @code{JOIN} + @code{GROUP} + @code{INTO OUTFILE},
+the result wasn't grouped.
+@item
+@code{LIKE} with @code{'_'} as last character didn't work. Fixed.
+@item
+Added extended ANSI SQL @code{TRIM()} function.
+@item
+Added @code{CURTIME()}.
+@item
+Added @code{ENCRYPT()} function by Zeev Suraski.
+@item
+Fixed better @code{FOREIGN KEY} syntax skipping. New reserved words:
+@code{MATCH}, @code{FULL}, @code{PARTIAL}.
+@item
+@code{mysqld} now allows IP number and hostname to the @code{--bind-address}
+option.
+@item
+Added @code{SET OPTION CHARACTER SET cp1251_koi8} to enable conversions of
+data to/from cp1251_koi8.
+@item
+Lots of changes for Win95 port. In theory, this version should now be
+easily portable to Win95.
+@item
+Changed the @code{CREATE COLUMN} syntax of @code{NOT NULL} columns to be after
+the @code{DEFAULT} value, as specified in the ANSI SQL standard. This will
+make @code{mysqldump} with @code{NOT NULL} and default values incompatible with
+@strong{MySQL} 3.20.
+@item
+Added many function name aliases so the functions can be used with
+ODBC or ANSI SQL92 syntax.
+@item
+Fixed syntax of @code{ALTER TABLE tbl_name ALTER COLUMN col_name SET DEFAULT
+NULL}.
+@item
+Added @code{CHAR} and @code{BIT} as synonyms for @code{CHAR(1)}.
+@item
+Fixed core dump when updating as a user who has only @strong{select} privilege.
+@item
+@code{INSERT ... SELECT ... GROUP BY} didn't work in some cases. An
+@code{Invalid use of group function} error occurred.
+@item
+When using @code{LIMIT}, @code{SELECT} now always uses keys instead of record
+scan. This will give better performance on @code{SELECT} and a @code{WHERE}
+that matches many rows.
+@item
+Added Russian error messages.
+@end itemize
+
+@node News-3.21.11, News-3.21.10, News-3.21.12, News-3.21.x
+@appendixsubsec Changes in release 3.21.11
+
+@itemize @bullet
+@item
+Configure changes.
+@item
+@strong{MySQL} now works with the new thread library on BSD/OS 3.0.
+@item
+Added new group functions @code{BIT_OR()} and @code{BIT_AND()}.
+@item
+Added compatibility functions @code{CHECK} and @code{REFERENCES}.
+@code{CHECK} is now a reserved word.
+@item
+Added @code{ALL} option to @code{GRANT} for better compatibility. (@code{GRANT}
+is still a dummy function.)
+@item
+Added partly-translated dutch messages.
+@item
+Fixed bug in @code{ORDER BY} and @code{GROUP BY} with @code{NULL} columns.
+@item
+Added function @code{last_insert_id()} to retrieve last @code{AUTO_INCREMENT}
+value. This is intended for clients to ODBC that can't use the
+@code{mysql_insert_id()} API function, but can be used by any client.
+@item
+Added @code{--flush-logs} option to @code{mysqladmin}.
+@item
+Added command @code{STATUS} to @code{mysql}.
+@item
+Fixed problem with @code{ORDER BY}/@code{GROUP BY} because of bug in @code{gcc}.
+@item
+Fixed problem with @code{INSERT ... SELECT ... GROUP BY}.
+@end itemize
+
+@node News-3.21.10, News-3.21.9, News-3.21.11, News-3.21.x
+@appendixsubsec Changes in release 3.21.10
+
+@itemize @bullet
+@item
+New @code{mysqlaccess}.
+@item
+@code{CREATE} now supports all ODBC types and the @code{mSQL} @code{TEXT} type.
+All ODBC 2.5 functions are also supported (added @code{REPEAT}). This provides
+better portability.
+@item
+Added text types @code{TINYTEXT}, @code{TEXT}, @code{MEDIUMTEXT} and
+@code{LONGTEXT}. These are actually @code{BLOB}types, but all searching is
+done in case-insensitive fashion.
+@item
+All old @code{BLOB} fields are now @code{TEXT} fields. This only
+changes that all searching on strings is done in case-sensitive fashion.
+You must do an @code{ALTER TABLE} and change the field type to @code{BLOB}
+if you want to have tests done in case-sensitive fashion.
+@item
+Fixed some @code{configure} issues.
+@item
+Made the locking code a bit safer. Fixed very unlikely
+deadlock situation.
+@item
+Fixed a couple of bugs in the range optimizer. Now the new range benchmark
+@code{test-select} works.
+@end itemize
+
+@node News-3.21.9, News-3.21.8, News-3.21.10, News-3.21.x
+@appendixsubsec Changes in release 3.21.9
+
+@itemize @bullet
+@item
+Added @code{--enable-unix-socket=pathname} option to @code{configure}.
+@item
+Fixed a couple of portability problems with include files.
+@item
+Fixed bug in range calculation that could return empty
+set when searching on multiple key with only one entry (very rare).
+@item
+Most things ported to FSU Pthreads, which should allow @strong{MySQL} to
+run on SCO. @xref{SCO}.
+@end itemize
+
+@node News-3.21.8, News-3.21.7, News-3.21.9, News-3.21.x
+@appendixsubsec Changes in release 3.21.8
+
+@itemize @bullet
+@item
+Works now in Solaris 2.6.
+@item
+Added handling of calculation of @code{SUM()} functions.
+For example, you can now use @code{SUM(column)/COUNT(column)}.
+@item
+Added handling of trigometric functions:
+@code{PI()}, @code{ACOS()}, @code{ASIN()}, @code{ATAN()}, @code{COS()},
+@code{SIN()} and @code{TAN()}.
+@item
+New languages: norwegian, norwegian-ny and portuguese.
+@item
+Fixed parameter bug in @code{net_print()} in @file{procedure.cc}.
+@item
+Fixed a couple of memory leaks.
+@item
+Now allow also the old @code{SELECT ... INTO OUTFILE} syntax.
+@item
+Fixed bug with @code{GROUP BY} and @code{SELECT} on key with many values.
+@item
+@code{mysql_fetch_lengths()} sometimes returned incorrect lengths when you used
+@code{mysql_use_result()}. This affected at least some cases of
+@code{mysqldump --quick}.
+@item
+Fixed bug in optimization of @code{WHERE const op field}.
+@item
+Fixed problem when sorting on @code{NULL} fields.
+@item
+Fixed a couple of 64-bit (Alpha) problems.
+@item
+Added @code{--pid-file=#} option to @code{mysqld}.
+@item
+Added date formatting to @code{FROM_UNIXTIME()}, originally by Zeev Suraski.
+@item
+Fixed bug in @code{BETWEEN} in range optimizer (Did only test = of the first
+argument).
+@item
+Added machine-dependent files for MIT-pthreads i386-SCO. There is probably
+more to do to get this to work on SCO 3.5.
+@end itemize
+
+@node News-3.21.7, News-3.21.6, News-3.21.8, News-3.21.x
+@appendixsubsec Changes in release 3.21.7
+
+@itemize @bullet
+@item
+Changed @file{Makefile.am} to take advantage of Automake 1.2.
+@item
+Added the beginnings of a benchmark suite.
+@item
+Added more secure password handling.
+@item
+Added new client function @code{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.x server when running
+without @code{--old-protocol}. The client code is backward compatible.
+More information can be found in the @file{README} file!
+@item
+Fixed some problems when using very long, illegal names.
+@end itemize
+
+@node News-3.21.6, News-3.21.5, News-3.21.7, News-3.21.x
+@appendixsubsec Changes in release 3.21.6
+
+@itemize @bullet
+@item
+Fixed more portability issues (incorrect @code{sigwait} and @code{sigset}
+defines).
+@item
+@code{configure} should now be able to detect the last argument to
+@code{accept()}.
+@end itemize
+
+@node News-3.21.5, News-3.21.4, News-3.21.6, News-3.21.x
+@appendixsubsec Changes in release 3.21.5
+
+@itemize @bullet
+@item
+Should now work with FreeBSD 3.0 if used with
+@file{FreeBSD-3.0-libc_r-1.0.diff},
+which can be found at @uref{http://www.mysql.com/Downloads/Patches/}.
+@item
+Added new option @code{-O tmp_table_size=#} to @code{mysqld}.
+@item
+New function @code{FROM_UNIXTIME(timestamp)} which returns a date string in
+'YYYY-MM-DD HH:MM:DD' format.
+@item
+New function @code{SEC_TO_TIME(seconds)} which returns a string in
+'HH:MM:SS' format.
+@item
+New function @code{SUBSTRING_INDEX()}, originally by Zeev Suraski.
+@end itemize
+
+@node News-3.21.4, News-3.21.3, News-3.21.5, News-3.21.x
+@appendixsubsec Changes in release 3.21.4
+
+@itemize @bullet
+@item
+Should now configure and compile on OSF1 4.0 with the DEC compiler.
+@item
+Configuration and compilation on BSD/OS 3.0 works, but due to some bugs in
+BSD/OS 3.0, @code{mysqld} doesn't work on it yet.
+@item
+Configuration and compilation on FreeBSD 3.0 works, but I couldn't get
+@code{pthread_create} to work.
+@end itemize
+
+@node News-3.21.3, News-3.21.2, News-3.21.4, News-3.21.x
+@appendixsubsec Changes in release 3.21.3
+
+@itemize @bullet
+@item
+Added reverse check lookup of hostnames to get better security.
+@item
+Fixed some possible buffer overflows if filenames that are too long are used.
+@item
+@code{mysqld} doesn't accept hostnames that start with digits followed by a
+@code{'.'}, because the hostname may look like an IP number.
+@item
+Added @code{--skip-networking} option to @code{mysqld}, to only allow socket
+connections. (This will not work with MIT-pthreads!)
+@item
+Added check of too long table names for alias.
+@item
+Added check if database name is okay.
+@item
+Added check if too long table names.
+@item
+Removed incorrect @code{free()} that killed the server on
+@code{CREATE DATABASE} or @code{DROP DATABASE}.
+@item
+Changed some @code{mysqld} @code{-O} options to better names.
+@item
+Added @code{-O join_cache_size=#} option to @code{mysqld}.
+@item
+Added @code{-O max_join_size=#} option to @code{mysqld}, to be able to set a
+limit how big queries (in this case big = slow) one should be able to handle
+without specifying @code{SET OPTION SQL_BIG_SELECTS=1}. A # = is about 10
+examined records. The default is ``unlimited''.
+@item
+When comparing a @code{TIME}, @code{DATE}, @code{DATETIME} or @code{TIMESTAMP}
+column to a constant, the constant is converted to a time value before
+performing the comparison.
+This will make it easier to get ODBC (particularly Access97) to work with
+the above types. It should also make dates easier to use and the comparisons
+should be quicker than before.
+@item
+Applied patch from Jochen Wiedmann that allows @code{query()} in
+@code{mysqlperl} to take a query with @code{\0} in it.
+@item
+Storing a timestamp with a 2-digit year (@code{YYMMDD}) didn't work.
+@item
+Fix that timestamp wasn't automatically updated if set in an @code{UPDATE}
+clause.
+@item
+Now the automatic timestamp field is the FIRST timestamp field.
+@item
+@code{SELECT * INTO OUTFILE}, which didn't correctly if the outfile already
+existed.
+@item
+@code{mysql} now shows the thread ID when starting or doing a reconnect.
+@item
+Changed the default sort buffer size from 2M to 1M.
+@end itemize
+
+@node News-3.21.2, News-3.21.0, News-3.21.3, News-3.21.x
+@appendixsubsec Changes in release 3.21.2
+
+@itemize @bullet
+@item
+The range optimizer is coded, but only 85% tested. It can be enabled with
+@code{--new}, but it crashes core a lot yet...
+@item
+More portable. Should compile on AIX and alpha-digital.
+At least the @code{isam} library should be relatively 64-bit clean.
+@item
+New @code{isamchk} which can detect and fix more problems.
+@item
+New options for @code{isamlog}.
+@item
+Using new version of Automake.
+@item
+Many small portability changes (from the AIX and alpha-digital port)
+Better checking of pthread(s) library.
+@item
+czech error messages by @email{snajdr@@pvt.net}.
+@item
+Decreased size of some buffers to get fewer problems on systems with little
+memory. Also added more checks to handle ``out of memory'' problems.
+@item
+@code{mysqladmin}: you can now do @code{mysqladmin kill 5,6,7,8} to kill
+multiple threads.
+@item
+When the maximum connection limit is reached, one extra connection by a user
+with the @strong{PROCESS_ACL} privilege is granted.
+@item
+Added @code{-O backlog=#} option to @code{mysqld}.
+@item
+Increased maximum packet size from 512K to 1024K for client.
+@item
+Almost all of the function code is now tested in the internal test suite.
+@item
+@code{ALTER TABLE} now returns warnings from field conversions.
+@item
+Port changed to 3306 (got it reserved from ISI).
+@item
+Added a fix for Visual FoxBase so that any schema name from a table
+specification is automatically removed.
+@item
+New function @code{ASCII()}.
+@item
+Removed function @code{BETWEEN(a,b,c)}. Use the standard ANSI
+synax instead: @code{expr BETWEEN expr AND expr}.
+@item
+@strong{MySQL} no longer has to use an extra temporary table when sorting
+on functions or @code{SUM()} functions.
+@item
+Fixed bug that you couldn't use @code{tbl_name.field_name} in @code{UPDATE}.
+@item
+Fixed @code{SELECT DISTINCT} when using 'hidden group'. For example:
+@example
+mysql> SELECT DISTINCT MOD(some_field,10) FROM test
+ GROUP BY some_field;
+@end example
+Note: @code{some_field} is normally in the @code{SELECT} part. ANSI SQL should
+require it.
+@end itemize
+
+@node News-3.21.0, , News-3.21.2, News-3.21.x
+@appendixsubsec Changes in release 3.21.0
+
+@itemize @bullet
+@item
+New reserved words used: @code{INTERVAL}, @code{EXPLAIN}, @code{READ},
+@code{WRITE}, @code{BINARY}.
+@item
+Added ODBC function @code{CHAR(num,...)}.
+@item
+New operator @code{IN}. This uses a binary search to find a match.
+@item
+New command @code{LOCK TABLES tbl_name [AS alias] @{READ|WRITE@} ...}
+@item
+Added @code{--log-update} option to @code{mysqld}, to get a log suitable for
+incremental updates.
+@item
+New command @code{EXPLAIN SELECT ...} to get information about how the
+optimizer will do the join.
+@item
+For easier client code, the client should no longer use
+@code{FIELD_TYPE_TINY_BLOB}, @code{FIELD_TYPE_MEDIUM_BLOB},
+@code{FIELD_TYPE_LONG_BLOB} or @code{FIELD_TYPE_VAR_STRING} (as
+previously returned by @code{mysql_list_fields}). You should instead only use
+@code{FIELD_TYPE_BLOB} or @code{FIELD_TYPE_STRING}. If you want exact
+types, you should use the command @code{SHOW FIELDS}.
+@item
+Added varbinary syntax: @code{0x######} which can be used as a string
+(default) or a number.
+@item
+@code{FIELD_TYPE_CHAR} is renamed to @code{FIELD_TYPE_TINY}.
+@item
+Changed all fields to C++ classes.
+@item
+Removed FORM struct.
+@item
+Fields with @code{DEFAULT} values no longer need to be @code{NOT NULL}.
+@item
+New field types:
+@table @code
+@item ENUM
+A string which can take only a couple of defined values. The value is
+stored as a 1-3 byte number that is mapped automatically to a string.
+This is sorted according to string positions!
+@item SET
+A string which 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 set member. This is sorted according to the unsigned value
+of the stored packed number.
+@end table
+@item
+Now all function calculation is done with @code{double} or @code{long long}.
+This will provide the full 64-bit range with bit functions and fix some
+conversions that previously could result in precision losses. One should
+avoid using @code{unsigned long long} columns with full 64-bit range
+(numbers bigger than 9223372036854775807) because calculations are done
+with @code{signed long long}.
+@item
+@code{ORDER BY} will now put @code{NULL} field values first. @code{GROUP BY}
+will also work with @code{NULL} values.
+@item
+Full @code{WHERE} with expressions.
+@item
+New range optimizer that can resolve ranges when some keypart prefix is
+constant. Example:
+@example
+mysql> SELECT * FROM tbl_name
+ WHERE key_part_1="customer"
+ AND key_part_2>=10 AND key_part_2<=10;
+@end example
+@end itemize
+
+@node News-3.20.x, News-3.19.x, News-3.21.x, News
+@appendixsec Changes in release 3.20.x
+
+Changes from 3.20.18 to 3.20.32b are not documented here because the
+3.21 release branched here. And the relevant changes are also
+documented as changes to the 3.21 version.
+
+@menu
+* News-3.20.18:: Changes in release 3.20.18
+* News-3.20.17:: Changes in release 3.20.17
+* News-3.20.16:: Changes in release 3.20.16
+* News-3.20.15:: Changes in release 3.20.15
+* News-3.20.14:: Changes in release 3.20.14
+* News-3.20.13:: Changes in release 3.20.13
+* News-3.20.11:: Changes in release 3.20.11
+* News-3.20.10:: Changes in release 3.20.10
+* News-3.20.9:: Changes in release 3.20.9
+* News-3.20.8:: Changes in release 3.20.8
+* News-3.20.7:: Changes in release 3.20.7
+* News-3.20.6:: Changes in release 3.20.6
+* News-3.20.3:: Changes in release 3.20.3
+* News-3.20.0:: Changes in releases 3.20.0
+@end menu
+
+@node News-3.20.18, News-3.20.17, News-3.20.x, News-3.20.x
+@appendixsubsec Changes in release 3.20.18
+
+@itemize @bullet
+@item
+Added @code{-p#} (remove @code{#} directories from path) to @code{isamlog}.
+All files are written with a relative path from the database directory
+Now @code{mysqld} shouldn't crash on shutdown when using the
+@code{--log-isam} option.
+@item
+New @code{mysqlperl} version. It is now compatible with @code{msqlperl-0.63}.
+@item
+New @code{DBD} module available at @uref{http://www.mysql.com/Downloads/Contrib/}
+site.
+@item
+Added group function @code{STD()} (standard deviation).
+@item
+The @code{mysqld} server is now compiled by default without debugging
+information. This will make the daemon smaller and faster.
+@item
+Now one usually only has to specify the @code{--basedir} option to
+@code{mysqld}. All other paths are relative in a normal installation.
+@item
+@code{BLOB} columns sometimes contained garbage when used with a @code{SELECT}
+on more than one table and @code{ORDER BY}.
+@item
+Fixed that calculations that are not in @code{GROUP BY} work as expected
+(ANSI SQL extension).
+Example:
+@example
+mysql> SELECT id,id+1 FROM table GROUP BY id;
+@end example
+@item
+The test of using @code{MYSQL_PWD} was reversed. Now @code{MYSQL_PWD} is
+enabled as default in the default release.
+@item
+Fixed conversion bug which caused @code{mysqld} to core dump with
+Arithmetic error on Sparc-386.
+@item
+Added @code{--unbuffered} option to @code{mysql}, for new @code{mysqlaccess}.
+@item
+When using overlapping (unnecessary) keys and join over many tables,
+the optimizer could get confused and return 0 records.
+@end itemize
+
+@node News-3.20.17, News-3.20.16, News-3.20.18, News-3.20.x
+@appendixsubsec Changes in release 3.20.17
+
+@itemize @bullet
+@item
+You can now use @code{BLOB} columns and the functions @code{IS NULL} and
+@code{IS NOT NULL} in the @code{WHERE} clause.
+@item
+All communication packets and row buffers are now allocated dynamically
+on demand. The default value of @code{max_allowed_packet} is now 64K for
+the server and 512K for the client. This is mainly used to catch
+incorrect packets that could trash all memory. The server limit may be
+changed when it is started.
+@item
+Changed stack usage to use less memory.
+@item
+Changed @code{safe_mysqld} to check for running daemon.
+@item
+The @code{ELT()} function is renamed to @code{FIELD()}. The new
+@code{ELT()} function returns a value based on an index: @code{FIELD()}
+is the inverse of @code{ELT()} Example: @code{ELT(2,"A","B","C")} returns
+@code{"B"}. @code{FIELD("B","A","B","C")} returns @code{2}.
+@item
+@code{COUNT(field)}, where @code{field} could have a @code{NULL} value, now
+works.
+@item
+A couple of bugs fixed in @code{SELECT ... GROUP BY}.
+@item
+Fixed memory overrun bug in @code{WHERE} with many unoptimizable brace levels.
+@item
+Fixed some small bugs in the grant code.
+@item
+If hostname isn't found by @code{get_hostname}, only the IP is checked.
+Previously, you got @code{Access denied}.
+@item
+Inserts of timestamps with values didn't always work.
+@item
+@code{INSERT INTO ... SELECT ... WHERE} could give the error
+@code{Duplicated field}.
+@item
+Added some tests to @code{safe_mysqld} to make it ``safer''.
+@item
+@code{LIKE} was case sensitive in some places and case insensitive in others.
+Now @code{LIKE} is always case insensitive.
+@item
+@file{mysql.cc}: Allow @code{'#'} anywhere on the line.
+@item
+New command @code{SET OPTION SQL_SELECT_LIMIT=#}. See the FAQ for more details.
+@item
+New version of the @code{mysqlaccess} script.
+@item
+Change @code{FROM_DAYS()} and @code{WEEKDAY()} to also take a full
+@code{TIMESTAMP} or @code{DATETIME} as argument. Before they only took a
+number of type @code{YYYYMMDD} or @code{YYMMDD}.
+@item
+Added new function @code{UNIX_TIMESTAMP(timestamp_column)}.
+@end itemize
+
+@node News-3.20.16, News-3.20.15, News-3.20.17, News-3.20.x
+@appendixsubsec Changes in release 3.20.16
+
+@itemize @bullet
+@item
+More changes in MIT-pthreads to get them safer. Fixed also some link
+bugs at least in SunOS.
+@item
+Changed @code{mysqld} to work around a bug in MIT-pthreads. This makes multiple
+small @code{SELECT} operations 20 times faster. Now @code{lock_test.pl} should
+work.
+@item
+Added @code{mysql_FetchHash(handle)} to @code{mysqlperl}.
+@item
+The @code{mysqlbug} script is now distributed built to allow for reporting
+bugs that appear during the build with it.
+@item
+Changed @file{libmysql.c} to prefer @code{getpwuid()} instead of
+@code{cuserid()}.
+@item
+Fixed bug in @code{SELECT} optimizer when using many tables with the same
+column used as key to different tables.
+@item
+Added new latin2 and Russian KOI8 character tables.
+@item
+Added support for a dummy @code{GRANT} command to satisfy Powerbuilder.
+@end itemize
+
+@node News-3.20.15, News-3.20.14, News-3.20.16, News-3.20.x
+@appendixsubsec Changes in release 3.20.15
+
+@itemize @bullet
+@item
+Fixed fatal bug @code{packets out of order} when using MIT-pthreads.
+@item
+Removed possible loop when a thread waits for command from client
+and @code{fcntl()} fails. Thanks to Mike Bretz for finding this bug.
+@item
+Changed alarm loop in @file{mysqld.cc} because shutdown didn't always
+succeed in Linux.
+@item
+Removed use of @code{termbits} from @file{mysql.cc}. This conflicted with
+@code{glibc} 2.0.
+@item
+Fixed some syntax errors for at least BSD and Linux.
+@item
+Fixed bug when doing a @code{SELECT} as superuser without a database.
+@item
+Fixed bug when doing @code{SELECT} with group calculation to outfile.
+@end itemize
+
+@node News-3.20.14, News-3.20.13, News-3.20.15, News-3.20.x
+@appendixsubsec Changes in release 3.20.14
+
+@itemize @bullet
+@item
+If one gives @code{-p} or @code{--password} option to @code{mysql} without
+an argument, the user is solicited for the password from the tty.
+@item
+Added default password from @code{MYSQL_PWD} (by Elmar Haneke).
+@item
+Added command @code{kill} to @code{mysqladmin} to kill a specific
+@strong{MySQL} thread.
+@item
+Sometimes when doing a reconnect on a down connection this succeeded
+first on second try.
+@item
+Fixed adding an @code{AUTO_INCREMENT} key with @code{ALTER_TABLE}.
+@item
+@code{AVG()} gave too small value on some @code{SELECT}s with
+@code{GROUP BY} and @code{ORDER BY}.
+@item
+Added new @code{DATETIME} type (by Giovanni Maruzzelli
+@email{maruzz@@matrice.it}).
+@item
+Fixed that define @code{DONT_USE_DEFAULT_FIELDS} works.
+@item
+Changed to use a thread to handle alarms instead of signals on Solaris to
+avoid race conditions.
+@item
+Fixed default length of signed numbers. (George Harvey
+@email{georgeh@@pinacl.co.uk}.)
+@item
+Allow anything for @code{CREATE INDEX}.
+@item
+Add prezeros when packing numbers to @code{DATE}, @code{TIME} and
+@code{TIMESTAMP}.
+@item
+Fixed a bug in @code{OR} of multiple tables (gave empty set).
+@item
+Added many patches to MIT-pthreads. This fixes at least one lookup bug.
+@end itemize
+
+@node News-3.20.13, News-3.20.11, News-3.20.14, News-3.20.x
+@appendixsubsec Changes in release 3.20.13
+
+@itemize @bullet
+@item
+Added ANSI SQL94 @code{DATE} and @code{TIME} types.
+@item
+Fixed bug in @code{SELECT} with @code{AND}-@code{OR} levels.
+@item
+Added support for Slovenian characters. The @file{Contrib} directory contains
+source and instructions for adding other character sets.
+@item
+Fixed bug with @code{LIMIT} and @code{ORDER BY}.
+@item
+Allow @code{ORDER BY} and @code{GROUP BY} on items that aren't in the
+@code{SELECT} list.
+(Thanks to Wim Bonis @email{bonis@@kiss.de}, for pointing this out.)
+@item
+Allow setting of timestamp values in @code{INSERT}.
+@item
+Fixed bug with @code{SELECT ... WHERE ... = NULL}.
+@item
+Added changes for @code{glibc} 2.0. To get @code{glibc} to work, you should
+add the @file{gibc-2.0-sigwait-patch} before compiling @code{glibc}.
+@item
+Fixed bug in @code{ALTER TABLE} when changing a @code{NOT NULL} field to
+allow @code{NULL} values.
+@item
+Added some ANSI92 synonyms as field types to @code{CREATE TABLE}.
+@code{CREATE TABLE} now allows @code{FLOAT(4)} and @code{FLOAT(8)} to mean
+@code{FLOAT} and @code{DOUBLE}.
+@item
+New utility program @code{mysqlaccess} by @email{Yves.Carlier@@rug.ac.be}.
+This program shows the access rights for a specific user and the grant
+rows that determine this grant.
+@item
+Added @code{WHERE const op field} (by @email{bonis@@kiss.de}).
+@end itemize
+
+@node News-3.20.11, News-3.20.10, News-3.20.13, News-3.20.x
+@appendixsubsec Changes in release 3.20.11
+
+@itemize @bullet
+@item
+When using @code{SELECT ... INTO OUTFILE}, all temporary tables are ISAM
+instead of HEAP to allow big dumps.
+@item
+Changed date functions to be string functions. This fixed some ``funny''
+side effects when sorting on dates.
+@item
+Extended @code{ALTER TABLE} according to SQL92.
+@item
+Some minor compability changes.
+@item
+Added @code{--port} and @code{--socket} options to all utility programs and
+@code{mysqld}.
+@item
+Fixed MIT-pthreads @code{readdir_r()}. Now @code{mysqladmin create database}
+and @code{mysqladmin drop database} should work.
+@item
+Changed MIT-pthreads to use our @code{tempnam()}. This should fix the ``sort
+aborted'' bug.
+@item
+Added sync of records count in @code{sql_update}. This fixed slow updates
+on first connection. (Thanks to Vaclav Bittner for the test.)
+@end itemize
+
+@node News-3.20.10, News-3.20.9, News-3.20.11, News-3.20.x
+@appendixsubsec Changes in release 3.20.10
+
+@itemize @bullet
+@item
+New insert type: @code{INSERT INTO ... SELECT ...}
+@item
+@code{MEDIUMBLOB} fixed.
+@item
+Fixed bug in @code{ALTER TABLE} and @code{BLOB}s.
+@item
+@code{SELECT ... INTO OUTFILE} now creates the file in the current
+database directory.
+@item
+@code{DROP TABLE} now can take a list of tables.
+@item
+Oracle synonym @code{DESCRIBE} (@code{DESC}).
+@item
+Changes to @code{make_binary_distribution}.
+@item
+Added some comments to installation instructions about @code{configure}'s
+C++ link test.
+@item
+Added @code{--without-perl} option to @code{configure}.
+@item
+Lots of small portability changes.
+@end itemize
+
+@node News-3.20.9, News-3.20.8, News-3.20.10, News-3.20.x
+@appendixsubsec Changes in release 3.20.9
+
+@itemize @bullet
+@item
+@code{ALTER TABLE} didn't copy null bit. As a result, fields that were allowed
+to have @code{NULL} values were always @code{NULL}.
+@item
+@code{CREATE} didn't take numbers as @code{DEFAULT}.
+@item
+Some compatibility changes for SunOS.
+@item
+Removed @file{config.cache} from old distribution.
+@end itemize
+
+@node News-3.20.8, News-3.20.7, News-3.20.9, News-3.20.x
+@appendixsubsec Changes in release 3.20.8
+
+@itemize @bullet
+@item
+Fixed bug with @code{ALTER TABLE} and multi-part keys.
+@end itemize
+
+@node News-3.20.7, News-3.20.6, News-3.20.8, News-3.20.x
+@appendixsubsec Changes in release 3.20.7
+
+@itemize @bullet
+@item
+New commands: @code{ALTER TABLE}, @code{SELECT ... INTO OUTFILE} and
+@code{LOAD DATA INFILE}.
+@item
+New function: @code{NOW()}.
+@item
+Added new field @strong{file_priv} to @code{mysql/user} table.
+@item
+New script @code{add_file_priv} which adds the new field @strong{file_priv}
+to the @code{user} table. This script must be executed if you want to
+use the new @code{SELECT ... INTO} and @code{LOAD DATA INFILE ...} commands
+with a version of @strong{MySQL} earlier than 3.20.7.
+@item
+Fixed bug in locking code, which made @code{lock_test.pl} test fail.
+@item
+New files @file{NEW} and @file{BUGS}.
+@item
+Changed @file{select_test.c} and @file{insert_test.c} to include
+@file{config.h}.
+@item
+Added command @code{status} to @code{mysqladmin} for short logging.
+@item
+Increased maximum number of keys to 16 and maximum number of key parts to 15.
+@item
+Use of sub keys. A key may now be a prefix of a string field.
+@item
+Added @code{-k} option to @code{mysqlshow}, to get key information for a table.
+@item
+Added long options to @code{mysqldump}.
+@end itemize
+
+@node News-3.20.6, News-3.20.3, News-3.20.7, News-3.20.x
+@appendixsubsec Changes in release 3.20.6
+
+@itemize @bullet
+@item
+Portable to more systems because of MIT-pthreads, which will
+be used automatically if @code{configure} cannot find a @code{-lpthreads}
+library.
+@item
+Added GNU-style long options to almost all programs. Test with
+@code{@kbd{program} --help}.
+@item
+Some shared library support for Linux.
+@item
+The FAQ is now in @file{.texi} format and is available in @file{.html},
+@file{.txt} and @file{.ps} formats.
+@item
+Added new SQL function @code{RAND([init])}.
+@item
+Changed @code{sql_lex} to handle @code{\0} unquoted, but the client can't send
+the query through the C API, because it takes a str pointer.
+You must use @code{mysql_real_query()} to send the query.
+@item
+Added API function @code{mysql_get_client_info()}.
+@item
+@code{mysqld} now uses the @code{N_MAX_KEY_LENGTH} from @file{nisam.h} as
+the maximum allowed key length.
+@item
+The following now works:
+@example
+mysql> SELECT filter_nr,filter_nr FROM filter ORDER BY filter_nr;
+@end example
+Previously, this resulted in the error:
+@code{Column: 'filter_nr' in order clause is ambiguous}.
+@item
+@code{mysql} now outputs @code{'\0'}, @code{'\t'}, @code{'\n'} and @code{'\\'}
+when encountering ASCII 0, tab, newline or @code{'\'} while writing
+tab-separated output.
+This is to allow printing of binary data in a portable format.
+To get the old behavior, use @code{-r} (or @code{--raw}).
+@item
+Added german error messages (60 of 80 error messages translated).
+@item
+Added new API function @code{mysql_fetch_lengths(MYSQL_RES *)}, which
+returns an array of of column lengths (of type @code{uint}).
+@item
+Fixed bug with @code{IS NULL} in @code{WHERE} clause.
+@item
+Changed the optimizer a little to get better results when searching on a key
+part.
+@item
+Added @code{SELECT} option @code{STRAIGHT_JOIN} to tell the optimizer that
+it should join tables in the given order.
+@item
+Added support for comments starting with @code{'--'} in @file{mysql.cc}
+(Postgres syntax).
+@item
+You can have @code{SELECT} expressions and table columns in a @code{SELECT}
+which are not used in the group part. This makes it efficient to implement
+lookups. The column that is used should be a constant for each group because
+the value is calculated only once for the first row that is found for a group.
+@example
+mysql> SELECT id,lookup.text,sum(*) FROM test,lookup
+ WHERE test.id=lookup.id GROUP BY id;
+@end example
+@item
+Fixed bug in @code{SUM(function)} (could cause a core dump).
+@item
+Changed @code{AUTO_INCREMENT} placement in the SQL query:
+@example
+INSERT into table (auto_field) values (0);
+@end example
+inserted 0, but it should insert an @code{AUTO_INCREMENT} value.
+@item
+@file{mysqlshow.c}: Added number of records in table. Had to change the
+client code a little to fix this.
+@item
+@code{mysql} now allows doubled @code{''} or @code{""} within strings for
+embedded @code{'} or @code{"}.
+@item
+New math functions:
+@code{EXP()}, @code{LOG()}, @code{SQRT()}, @code{ROUND()}, @code{CEILING()}.
+@end itemize
+
+@node News-3.20.3, News-3.20.0, News-3.20.6, News-3.20.x
+@appendixsubsec Changes in release 3.20.3
+
+@itemize @bullet
+@item
+The @code{configure} source now compiles a thread-free client library
+@code{-lmysqlclient}. This is the only library that needs to be linked
+with client applications. When using the binary releases, you must
+link with @code{-lmysql -lmysys -ldbug -lstrings} as before.
+@item
+New @code{readline} library from @code{bash-2.0}.
+@item
+LOTS of small changes to @code{configure} and makefiles (and related source).
+@item
+It should now be possible to compile in another directory using
+@code{VPATH}. Tested with GNU Make 3.75.
+@item
+@code{safe_mysqld} and @code{mysql.server} changed to be more compatible
+between the source and the binary releases.
+@item
+@code{LIMIT} now takes one or two numeric arguments.
+If one argument is given, it indicates the maximum number of rows in
+a result. If two arguments are given, the first argument indicates the offset
+of the first row to return, the second is the maximum number of rows.
+With this it's easy to do a poor man's next page/previous page WWW
+application.
+@item
+Changed name of SQL function @code{FIELDS()} to @code{ELT()}.
+Changed SQL function @code{INTERVALL()} to @code{INTERVAL()}.
+@item
+Made @code{SHOW COLUMNS} a synonym for @code{SHOW FIELDS}.
+Added compatibility syntax @code{FRIEND KEY} to @code{CREATE TABLE}. In
+@strong{MySQL}, this creates a non-unique key on the given columns.
+@item
+Added @code{CREATE INDEX} and @code{DROP INDEX} as compatibility functions.
+In @strong{MySQL}, @code{CREATE INDEX} only checks if the index exists and
+issues an error if it doesn't exist. @code{DROP INDEX} always succeeds.
+@item
+@file{mysqladmin.c}: added client version to version information.
+@item
+Fixed core dump bug in @code{sql_acl} (core on new connection).
+@item
+Removed @code{host}, @code{user} and @code{db} tables from database @code{test}
+in the distribution.
+@item
+@code{FIELD_TYPE_CHAR} can now be signed (-128 - 127) or unsigned (0 - 255)
+Previously, it was always unsigned.
+@item
+Bug fixes in @code{CONCAT()} and @code{WEEKDAY()}.
+@item
+Changed a lot of source to get @code{mysqld} to be compiled with SunPro
+compiler.
+@item
+SQL functions must now have a @code{'('} immediately after the function name
+(no intervening space).
+For example, @code{'user('} is regarded as beginning a function call, and
+@code{'user ('} is regarded as an identifier @code{user} followed by a
+@code{'('}, not as a function call.
+@end itemize
+
+@node News-3.20.0, , News-3.20.3, News-3.20.x
+@appendixsubsec Changes in release 3.20.0
+
+@itemize @bullet
+@item
+The source distribution is done with @code{configure} and Automake.
+It will make porting much easier. The @code{readline} library is included
+in the distribution.
+@item
+Separate client compilation:
+the client code should be very easy to compile on systems which
+don't have threads.
+@item
+The old Perl interface code is automatically compiled and installed.
+Automatic compiling of @code{DBD} will follow when the new @code{DBD} code
+is ported.
+@item
+Dynamic language support: @code{mysqld} can now be started with Swedish
+or English (default) error messages.
+@item
+New functions: @code{INSERT()}, @code{RTRIM()}, @code{LTRIM()} and
+@code{FORMAT()}.
+@item
+@code{mysqldump} now works correctly for all field types (even
+@code{AUTO_INCREMENT}). The format for @code{SHOW FIELDS FROM tbl_name}
+is changed so the @code{Type} column contains information suitable for
+@code{CREATE TABLE}. In previous releases, some @code{CREATE TABLE}
+information had to be patched when recreating tables.
+@item
+Some parser bugs from 3.19.5 (@code{BLOB} and @code{TIMESTAMP}) are corrected.
+@code{TIMESTAMP} now returns different date information depending on its
+create length.
+@item
+Changed parser to allow a database, table or field name to
+start with a number or @code{'_'}.
+@item
+All old C code from Unireg changed to C++ and cleaned up. This makes
+the daemon a little smaller and easier to understand.
+@item
+A lot of small bug fixes done.
+@item
+New @file{INSTALL} files (not final version) and some info regarding porting.
+@end itemize
+
+@node News-3.19.x, , News-3.20.x, News
+@appendixsec Changes in release 3.19.x
+
+@menu
+* News-3.19.5:: Changes in release 3.19.5
+* News-3.19.4:: Changes in release 3.19.4
+* News-3.19.3:: Changes in release 3.19.3
+@end menu
+
+@node News-3.19.5, News-3.19.4, News-3.19.x, News-3.19.x
+@appendixsubsec Changes in release 3.19.5
+
+@itemize @bullet
+@item
+Some new functions, some more optimization on joins.
+@item
+Should now compile clean on Linux (2.0.x).
+@item
+Added functions @code{DATABASE()}, @code{USER()}, @code{POW()},
+@code{LOG10()} (needed for ODBC).
+@item
+In a @code{WHERE} with an @code{ORDER BY} on fields from only one table,
+the table is now preferred as first table in a multi-join.
+@item
+@code{HAVING} and @code{IS NULL} or @code{IS NOT NULL} now works.
+@item
+A group on one column and a sort on a group function (@code{SUM()},
+@code{AVG()}...) didn't work together. Fixed.
+@item
+@code{mysqldump}: Didn't send password to server.
+@end itemize
+
+@node News-3.19.4, News-3.19.3, News-3.19.5, News-3.19.x
+@appendixsubsec Changes in release 3.19.4
+
+@itemize @bullet
+@item
+Fixed horrible locking bug when inserting in one thread and reading
+in another thread.
+@item
+Fixed one-off decimal bug. 1.00 was output as 1.0.
+@item
+Added attribute @code{'Locked'} to process list as info if a query is
+locked by another query.
+@item
+Fixed full magic timestamp. Timestamp length may now be 14, 12, 10, 8, 6, 4
+or 2 bytes.
+@item
+Sort on some numeric functions could sort incorrectly on last number.
+@item
+@code{IF(arg,syntax_error,syntax_error)} crashed.
+@item
+Added functions @code{CEILING()}, @code{ROUND()}, @code{EXP()}, @code{LOG()} and @code{SQRT()}.
+@item
+Enhanced @code{BETWEEN} to handle strings.
+@end itemize
+
+@node News-3.19.3, , News-3.19.4, News-3.19.x
+@appendixsubsec Changes in release 3.19.3
+
+@itemize @bullet
+@item
+Fixed @code{SELECT} with grouping on @code{BLOB} columns not to return
+incorrect @code{BLOB} info. Grouping, sorting and distinct on @code{BLOB}
+columns will not yet work as
+expected (probably it will group/sort by the first 7 characters in the
+@code{BLOB}). Grouping on formulas with a fixed string size (use @code{MID()}
+on a @code{BLOB}) should work.
+@item
+When doing a full join (no direct keys) on multiple tables with @code{BLOB}
+fields, the @code{BLOB} was garbage on output.
+@item
+Fixed @code{DISTINCT} with calculated columns.
+@end itemize
+
+@node Bugs, TODO, News, Top
+@appendix Known errors and design deficiencies in MySQL
+
+The following is known bugs in @strong{MySQL} 3.23.22 that will be fixed
+in the next release:
+@itemize @bullet
+@item
+Searching on part keys on BDB tables doesn't return all rows:
+
+@example
+CREATE TABLE t1 (
+ user_id int(10) DEFAULT '0' NOT NULL,
+ name varchar(100),
+ phone varchar(100),
+ ref_email varchar(100) DEFAULT '' NOT NULL,
+ detail varchar(200),
+ PRIMARY KEY (user_id,ref_email)
+)type=bdb;
+INSERT INTO t1 VALUES (10292,'sanjeev','29153373','sansh777.hotmail.com','xxx'),(10292,'shirish','2333604','shirish.yahoo.com','ddsds'),(10292,'sonali','323232','sonali.bolly.com','filmstar');
+select * from t1 where user_id=10292;
+@end example
+@end itemize
+
+Other known problems:
+
+@itemize @bullet
+@item
+You cannot build in another directory when using
+MIT-pthreads. Because this requires changes to MIT-pthreads, we are not
+likely to fix this.
+@item
+@code{BLOB} values can't ``reliably'' be used in @code{GROUP BY} or
+@code{ORDER BY} or @code{DISTINCT}. Only the first @code{max_sort_length}
+bytes (default 1024) are used when comparing @code{BLOB}bs in these cases.
+This can be changed with the @code{-O max_sort_length} option to
+@code{mysqld}. A workaround for most cases is to use a substring:
+@code{SELECT DISTINCT LEFT(blob,2048) FROM tbl_name}.
+@item
+Calculation is done with @code{BIGINT} or @code{DOUBLE} (both are
+normally 64 bits long). It depends on the function which precision one
+gets. The general rule is that bit functions are done with @code{BIGINT}
+precision, @code{IF}, and @code{ELT()} with @code{BIGINT} or @code{DOUBLE}
+precision and the rest with @code{DOUBLE} precision. One should try to
+avoid using bigger unsigned long long values than 63 bits
+(9223372036854775807) for anything else than bit fields!
+@item
+All string columns, except @code{BLOB} and @code{TEXT} columns, automatically
+have all trailing spaces removed when retrieved. For @code{CHAR} types this
+is okay, and may be regarded as a feature according to ANSI SQL92. The bug is
+that in @strong{MySQL}, @code{VARCHAR} columns are treated the same way.
+@item
+You can only have up to 255 @code{ENUM} and @code{SET} columns in one table.
+@item
+@code{safe_mysqld} re-directs all messages from @code{mysqld} to the
+@code{mysqld} log. One problem with this is that if you execute
+@code{mysqladmin refresh} to close and reopen the log,
+@code{stdout} and @code{stderr} are still redirected to the old log.
+If you use @code{--log} extensively, you should edit @code{safe_mysqld} to
+log to @file{'hostname'.err} instead of @file{'hostname'.log} so you can
+easily reclaim the space for the old log by deleting the old one and
+executing @code{mysqladmin refresh}.
+@item
+In the @code{UPDATE} statement, columns are updated from left to right.
+If you refer to a updated column, you will get the updated value instead of the
+original value. For example:
+@example
+mysql> UPDATE tbl_name SET KEY=KEY+1,KEY=KEY+1
+@end example
+will update @code{KEY} with @code{2} instead of with @code{1}.
+@item
+You can't use temporary tables more than once in the same query.
+
+@example
+select * from temporary_table, temporary_table as t2;
+@end example
+
+@item
+Because @strong{MySQL} allows you to work with table types that doesn't
+support transactions (and thus can't @code{rollback} data) some things
+behaves a little different in @strong{MySQL} than in other SQL servers:
+(This is just to ensure that @strong{MySQL} never need to do a rollback
+for a SQL command). This may be a little akward at times as column
+values must be checked in the application, but this will actually give
+you a nice speed increase as it allows @strong{MySQL} to do some
+optimizations that otherwice would be very hard to do.
+
+If you set a colum to a wrong value, @strong{MySQL} will instead of doing
+a rollback instead store the @code{best possible value} in the column.
+
+@itemize @bullet
+@item
+If you try to store a value outside of the range in a numerical column,
+@strong{MySQL} will instead store the smallest or biggest possible value in
+the column.
+@item
+If you try to store a string, that doesn't start with a number, into a
+numerical column @strong{MySQL} will store 0 into it.
+@item
+If you try to to store @code{NULL} into a column that doesn't take
+@code{NULL} values, @code{MySQL} will store 0 or @code{''} (empty
+string) in it instead. (This behavour can however be changed with the
+-DDONT_USE_DEFAULT_FIELDS compile option).
+@item
+@strong{MySQL} allows you to store some wrong date values into
+@code{DATE} and @code{DATETIME} columns. (Like 2000-02-31 or 2000-02-00).
+If the date is totally wrong, @strong{MySQL} will store the special
+0000-00-00 date value in the column.
+@item
+If you set an @code{enum} to an not supported value, it will be set to
+the error value 'empty string', with numeric value 0.
+@end itemize
+@item
+If you execute a @code{PROCEDURE} on a query with returns an empty set then
+in some cases the @code{PROCEDURE} will not transform the columns.
+@end itemize
+
+The following is known bugs in earlier versions of @strong{MySQL}:
+
+@itemize @bullet
+@item
+You can get a hanged thread if you do a @code{DROP TABLE} on a table that is
+one among many tables that is locked with @code{LOCK TABLES}.
+
+@item
+In the following case you can get a core dump:
+@enumerate
+@item
+Delayed insert handler has pending inserts to a table.
+@item
+@code{LOCK table} with @code{WRITE}
+@item
+@code{FLUSH TABLES}
+@end enumerate
+
+@item
+Before @strong{MySQL} 3.23.2 an @code{UPDATE} that updated a key with
+a @code{WHERE} on the same key may have failed because the key was used to
+search for records and the same row may have been found multiple times:
+
+@example
+UPDATE tbl_name SET KEY=KEY+1 WHERE KEY > 100;
+@end example
+
+A workaround is to use:
+
+@example
+mysql> UPDATE tbl_name SET KEY=KEY+1 WHERE KEY+0 > 100;
+@end example
+
+This will work because @strong{MySQL} will not use index on expressions in
+the @code{WHERE} clause.
+@item
+Before @strong{MySQL} 3.23, all numeric types where treated as fixed-point
+fields. That means you had to specify how many decimals a floating-point
+field shall have. All results were returned with the correct number of
+decimals.
+@end itemize
+
+For platform-specific bugs, see the sections about compiling and porting.
+
+@cindex TODO
+@node TODO, Porting, Bugs, Top
+@appendix List of things we want to add to MySQL in the future (The TODO)
+
+@menu
+* TODO future:: Things that must done in the very near future
+* TODO sometime:: Things that have to be done sometime
+* TODO unplanned:: Some things we don't have any plans to do
+@end menu
+
+Everything in this list is in the order it will be done. If you want to
+affect the priority order, please register a license or support us and
+tell us what you want to have done more quickly. @xref{Licensing and Support}.
+
+@node TODO future, TODO sometime, TODO, TODO
+@appendixsec Things that must done in the real near future
+
+@itemize @bullet
+@item
+Fail safe replication.
+@item
+Optimize, test and document transactions safe tables
+@item
+Subqueries. @code{select id from t where grp in (select grp from g where u > 100)}
+@item
+Port of @strong{MySQL} to BeOS.
+@item
+Add a temporary key buffer cache during @code{insert/delete/update} so that we
+can gracefully recover if the index file gets full.
+@item
+If you perform an @code{ALTER TABLE} on a table that is symlinked to another
+disk, create temporary tables on this disk.
+@item
+@code{RENAME table as table, table as table [,...]}
+@item
+Allow users to change startup options.
+@item
+FreeBSD and MIT-pthreads; Do sleeping threads take CPU?
+@item
+Check if locked threads take any CPU.
+@item
+Change to use mkstemp() instead of tempnam() for system that supports the call.
+We need to add a my_mkstemp() function in mysys and also change the cache
+code to not create the filename until we do the actual open.
+@item
+Allow join on key parts (optimization issue).
+@item
+Entry for @code{DECRYPT()}.
+@item
+@code{INSERT SQL_CONCURRENT} and @code{mysqld --concurrent-insert} to do
+a concurrent insert at the end of the file if the file is read-locked.
+@item
+Remember @code{FOREIGN} key definitions in the @file{.frm} file.
+@item
+Server side cursors.
+@item
+Check if @code{lockd} works with modern Linux kernels; If not, we have
+to fix @code{lockd}! To test this, start @code{mysqld} with
+@code{--enable-locking} and run the different fork* test suits. They shouldn't
+give any errors if @code{lockd} works.
+@item
+Allow SQL variables in @code{LIMIT}, like in @code{LIMIT @@a,@@b}.
+@item
+Don't add automatic @code{DEFAULT} values to columns. Give an error when using
+an @code{INSERT} that doesn't contain a column that doesn't have a
+@code{DEFAULT}.
+@item
+Caching of queries and results. This should be done as a separated
+module that examines each query and if this is query is in the cache
+the cached result should be returned. When one updates a table one
+should remove as few queries as possible from the cache.
+This should give a big speed bost on machines with much RAM where
+queries are often repeated (like WWW applications).
+One idea would be to only cache queries of type:
+@code{SELECT CACHED ....}
+@item
+Fix @file{libmysql.c} to allow two @code{mysql_query()} commands in a row
+without reading results or give a nice error message when one does this.
+@item
+Optimize @code{BIT} type to take 1 bit (now @code{BIT} takes 1 char).
+@item
+Check why MIT-pthreads @code{ctime()} doesn't work on some FreeBSD systems.
+@item
+Add @code{ORDER BY} to update. This would be handy with functions like:
+@code{generate_id(start,step)}.
+@item
+Add an @code{IMAGE} option to @code{LOAD DATA INFILE} to not update
+@code{TIMESTAMP} and @code{AUTO_INCREMENT} fields.
+@item
+Make @code{LOAD DATA INFILE} understand a syntax like:
+@example
+LOAD DATA INFILE 'file_name.txt' INTO TABLE tbl_name
+TEXT_FIELDS (text_field1, text_field2, text_field3)
+SET table_field1=concatenate(text_field1, text_field2), table_field3=23
+IGNORE text_field3
+@end example
+@item
+@code{LOAD DATA INFILE 'file_name' INTO TABLE 'table_name' ERRORS TO err_table_name}
+which would cause any errors/warnings to be logged into the err_table_name
+table. That table would have a structure like:
+
+@example
+line_number - line number in data file
+error_message - the error/warning message
+and maybe
+data_line - the line from the data file
+@end example
+@item
+We should extend @code{LOAD DATA INFILE} so that we can skip over extra
+columns in the text file.
+@item
+Add true @code{VARCHAR} support (There is already support for this in MyISAM).
+@item
+Automatic output from @code{mysql} to netscape.
+@item
+@code{LOCK DATABASES}. (with various options)
+@item
+Change sort to allocate memory in ``hunks'' to get better memory utilization.
+@item
+@code{DECIMAL} and @code{NUMERIC} types can't read exponential numbers;
+@code{Field_decimal::store(const char *from,uint len)} must be recoded
+to fix this.
+@item
+Fix @code{mysql.cc} to do fewer @code{malloc()} calls when hashing field
+names.
+@item
+Functions:
+ADD_TO_SET(value,set) and REMOVE_FROM_SET(value,set)
+@item
+Add use of @code{t1 JOIN t2 ON ...} and @code{t1 JOIN t2 USING ...}
+Currently, you can only use this syntax with @code{LEFT JOIN}.
+@item
+Add full support for @code{unsigned long long} type.
+@item
+Function @code{CASE}.
+@item
+Many more variables for @code{show status}. Counts for:
+@code{INSERT}/@code{DELETE}/@code{UPDATE} statements. Records reads and
+updated. Selects on 1 table and selects with joins. Mean number of
+tables in select. Key buffer read/write hits (logical and real).
+@code{ORDER BY}, @code{GROUP BY}, temporary tables created.
+@item
+If you abort @code{mysql} in the middle of a query, you should open
+another connection and kill the old running query.
+Alternatively, an attempt should be made to detect this in the server.
+@item
+Add a handler interface for table information so you can use it as a system
+table. This would be a bit slow if you requested information about all tables,
+but very flexible. @code{SHOW INFO FROM tbl_name} for basic table information
+should be implemented.
+@item
+Add support for UNICODE.
+@item
+@code{NATURAL JOIN}.
+@item
+Oracle like @code{CONNECT BY PRIOR ...} to search hierarchy structures.
+@item
+@code{RENAME DATABASE}
+@item
+@code{mysqladmin copy database new-database}.
+@item
+Processlist should show number of queries/thread.
+@item
+@code{DELETE} and @code{REPLACE} options to the @code{UPDATE} statement
+(this will delete rows when one gets a dupplicate key error while updating).
+@item
+Change the format of @code{DATETIME} to store fractions of seconds.
+@item
+Add all missing ANSI92 and ODBC 3.0 types.
+@item
+Change table names from empty strings to @code{NULL} for calculated columns.
+@item
+Don't use 'Item_copy_string' on numerical values to avoid
+number->string->number conversion in case of:
+@code{SELECT COUNT(*)*(id+0) FROM table_name GROUP BY id}
+@item
+Make it possible to use the new GNU regexp library instead of the current
+one (The GNU library should be much faster than the old one).
+@item
+Change that @code{ALTER TABLE} doesn't abort clients that executes
+@code{INSERT DELAYED}.
+@item
+Allow @code{select a from crash_me left join crash_me2 using (a)}; In this
+case a is assumed to come from the crash_me table.
+@item
+Fix that when columns referenced in an @code{UPDATE} clause contains the old
+values before the update started.
+@item
+Allow update of varibles in @code{UPDATE} statements. For example:
+@code{UPDATE TABLE foo SET @@a=a+b,a=@@a, b=@@a+c}
+@item
+@code{myisamchk}, @code{REPAIR} and @code{OPTIMIZE TABLE} should be able
+to handle cases where the data and/or index files are symbolic links.
+@item
+Add simulation of @code{pread()}/@code{pwrite()} on windows to enable
+concurrent inserts.
+@item
+A logfile analyzer that could parsed out information about which tables
+are hit most often, how often multi-table joins are executed, etc. It
+should help users identify areas or table design that could be optimized
+to execute much more efficient queries.
+@end itemize
+
+@node TODO sometime, TODO unplanned, TODO future, TODO
+@appendixsec Things that have to be done sometime
+
+@itemize @bullet
+@item
+Implement function: @code{get_changed_tables(timeout,table1,table2,...)}
+@item
+Atomic updates; This includes a language that one can even use for
+a set of stored procedures.
+@item
+@code{update items,month set items.price=month.price where items.id=month.id;}
+@item
+Change reading through tables to use memmap when possible. Now only
+compressed tables use memmap.
+@item
+Add a new privilege @strong{'Show_priv'} for @code{SHOW} commands.
+@item
+Make the automatic timestamp code nicer. Add timestamps to the update
+log with @code{SET TIMESTAMP=#;}
+@item
+Use read/write mutex in some places to get more speed.
+@item
+Full foreign key support. One probably wants to implement a procedural
+language first.
+@item
+Simple views (first on one table, later on any expression).
+@item
+Automatically close some tables if a table, temporary table or temporary files
+gets error 23 (not enough open files).
+@item
+When one finds a field=#, change all occurrences of field to #. Now this
+is only done for some simple cases.
+@item
+Change all const expressions with calculated expressions if possible.
+@item
+Optimize key = expression. At the moment only key = field or key =
+constant are optimized.
+@item
+Join some of the copy functions for nicer code.
+@item
+Change @file{sql_yacc.yy} to an inline parser to reduce its size and get
+better error messages (5 days).
+@item
+Change the parser to use only one rule per different number of arguments
+in function.
+@item
+Use of full calculation names in the order part. (For ACCESS97)
+@item
+@code{UNION}, @code{MINUS}, @code{INTERSECT} and @code{FULL OUTER JOIN}.
+(Currently only @code{LEFT OUTER JOIN} is supported)
+@item
+Allow @code{UNIQUE} on fields that can be @code{NULL}.
+@item
+@code{SQL_OPTION MAX_SELECT_TIME=#} to put a time limit on a query.
+@item
+Make the update log to a database.
+@item
+Negative @code{LIMIT} to retrieve data from the end.
+@item
+Alarm around client connect/read/write functions.
+@item
+Make a @code{mysqld} version which isn't multithreaded (3-5 days).
+@item
+Please note the changes to @code{safe_mysqld}: according to FSSTND (which
+Debian tries to follow) PID files should go into @file{/var/run/<progname>.pid}
+and log files into @file{/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.
+@item
+Better dynamic record layout to avoid fragmentation.
+@item
+@code{UPDATE SET blob=read_blob_from_file('my_gif') where id=1;}
+@item
+Allow a client to request logging.
+@item
+Add use of @code{zlib()} for @code{gzip}-ed files to @code{LOAD DATA INFILE}.
+@item
+Fix sorting and grouping of @code{BLOB} columns (partly solved now).
+@item
+Stored procedures. This is currently not regarded to be very
+important as stored procedures are not very standardized yet.
+Another problem is that true stored procedures make it much harder for
+the optimizer and in many cases the result is slower than before
+We will, on the other hand, add a simple (atomic) update language that
+can be used to write loops and such in the @strong{MySQL} server.
+@item
+Change to use semaphores when counting threads. One should first implement
+a semaphore library to MIT-pthreads.
+@item
+Don't assign a new @code{AUTO_INCREMENT} value when one sets a column to 0.
+Use @code{NULL} instead.
+@item
+Add full support for @code{JOIN} with parentheses.
+@item
+Reuse threads for systems with a lot of connections.
+@item
+As an alternative for one thread / connection manage a pool of threads
+to handle the queries.
+@item
+Allow one to get more than one lock with @code{GET_LOCK}. When doing this,
+one must also handle the possible deadlocks this change will introduce.
+@end itemize
+
+Time is given according to amount of work, not real time.
+
+@node TODO unplanned, , TODO sometime, TODO
+@appendixsec Some things we don't have any plans to do
+
+@itemize @bullet
+@item
+Nothing; In the long run we plan to be fully ANSI 92 / ANSI 99 compliant.
+@end itemize
+
+@node Porting, Regexp, TODO, Top
+@appendix 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, @email{Xavier.Leroy@@inria.fr}.
+
+The hard part of porting to a new Unix variant without good native
+thread support is probably to port MIT-pthreads. See
+@file{mit-pthreads/README} and
+@uref{http://www.humanfactor.com/pthreads/, Programming POSIX Threads}.
+
+The @strong{MySQL} distribution includes a patched version of
+Provenzano's Pthreads from MIT (see
+@uref{http://www.mit.edu:8001/people/proven/pthreads.html, MIT Pthreads
+web page}). This can be used for some operating systems that do not
+have POSIX threads.
+
+It is also possible to use another user level thread package named
+FSU Pthreads (see
+@uref{http://www.informatik.hu-berlin.de/~mueller/pthreads.html, FSU Pthreads
+home page}). This implementation is being used for the SCO port.
+
+See the @file{thr_lock.c} and @file{thr_alarm.c} programs in the @file{mysys}
+directory for some tests/examples of these problems.
+
+Both the server and the client need a working C++ compiler (we use @code{gcc}
+and have tried SparcWorks). Another compiler that is known to work is the
+Irix @code{cc}.
+
+To compile only the client use @code{./configure --without-server}.
+
+There is 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 @file{Makefile} or the configure script you must
+get Automake and Autoconf. We have used the @code{automake-1.2} and
+@code{autoconf-2.12} distributions.
+
+All steps needed to remake everything from the most basic files.
+
+@example
+/bin/rm */.deps/*.P
+/bin/rm -f config.cache
+aclocal
+autoheader
+aclocal
+automake
+autoconf
+./configure --with-debug --prefix='your installation directory'
+
+# The makefiles generated above need GNU make 3.75 or newer.
+# (called gmake below)
+gmake clean all install init-db
+@end example
+
+If you run into problems with a new port, you may have to do some debugging
+of @strong{MySQL}!
+@xref{Debugging server}.
+
+@strong{Note:} Before you start debugging @code{mysqld}, first get the test
+programs @code{mysys/thr_alarm} and @code{mysys/thr_lock} to work. This
+will ensure that your thread installation has even a remote chance to work!
+
+@menu
+* Debugging server:: Debugging a @strong{MySQL} server
+* Debugging client:: Debugging a @strong{MySQL} client
+* The DBUG package:: The DBUG package
+* Locking methods::
+* RTS-threads:: Comments about RTS threads
+* Thread packages:: Differences between different thread packages
+@end menu
+
+@node Debugging server, Debugging client, Porting, Porting
+@appendixsec Debugging a MySQL server
+
+If you are using some functionality that is very new in @strong{MySQL},
+you can try to run mysqld with the @code{--skip-new} (which will disable all
+new, potentially unsafe functionality) or with @code{--safe-mode} which
+disables a lot of optimization that may cause problems.
+@xref{Crashing}.
+
+If @code{mysqld} doesn't want to start, you should check that you don't have
+any @code{my.cnf} files that interfere with your setup!
+You can check your @code{my.cnf} arguments with @code{mysqld --print-defaults}
+and avoid using them by starting with @code{mysqld --no-defaults ...}.
+
+If you have some very specific problem, you can always try to debug
+@strong{MySQL}. To do this you must configure @strong{MySQL} with the
+option @code{--with-debug}. You can check whether or not
+@strong{MySQL} was compiled with debugging by doing: @code{mysqld
+--help}. If the @code{--debug} flag is listed with the options then you
+have debugging enabled. @code{mysqladmin ver} also lists the
+@code{mysqld} version as @code{mysql ... -debug} in this case.
+
+If you are using gcc or egcs, the recommended configure line is:
+
+@example
+CC=gcc CFLAGS="-O6" CXX=gcc CXXFLAGS="-O6 -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-debug --with-extra-charsets=complex
+@end example
+
+This will avoid problems with the @code{libstdc++} library and with C++
+exceptions (many compilers have problems with C++ exceptions in threaded
+code) and compile a @strong{MySQL} version with support for all character sets.
+
+If @code{mysqld} stops crashing when you compile it with
+@code{--with-debug}, you have probably found a compiler bug or a timing
+bug within @strong{MySQL}. In this case you can try to add @code{-g} to
+the @code{CFLAGS} and @code{CXXFLAGS} variables above and not use
+@code{--with-debug}. If @code{mysqld} now dies, you can at least attach
+to it with @code{gdb} or use @code{gdb} on the core file to find out
+what happened.
+
+If you can cause the @code{mysqld} server to crash quickly, you can try to
+create a trace file of this:
+
+Start the @code{mysqld} server with a trace log in @file{/tmp/mysql.trace}.
+The log file will get very @emph{BIG}.
+
+@code{mysqld --debug --log}
+
+or you can start it with
+
+@code{mysqld --debug=d,info,error,query,general,where:O,/tmp/mysql.trace}
+
+which only prints information with the most interesting tags.
+
+When you configure @strong{MySQL} for debugging you automatically enable a
+lot of extra safety check functions that monitor the health of @code{mysqld}.
+If they find something ``unexpected,'' an entry will be written to
+@code{stderr}, which @code{safe_mysqld} directs to the error log! This also
+means that if you are having some unexpected problems with @strong{MySQL} and
+are using a source distribution, the first thing you should do is to
+configure @strong{MySQL} for debugging! (The second thing, of course, is to
+send mail to @email{mysql@@lists.mysql.com} and ask for help. Please use the
+@code{mysqlbug} script for all bug reports or questions regarding the
+@strong{MySQL} version you are using!
+
+On most system you can also start @code{mysqld} from @code{gdb} to get
+more information if @code{mysqld} crashes.
+
+With some older @code{gdb} versions on Linux you must use @code{run
+--one-thread} if you want to be able to debug @code{mysqld} threads. In
+this case you can only have one thread active at a time.
+
+It's very hard to debug @strong{MySQL} under @code{gdb} if you do a lot of
+new connections the whole time as @code{gdb} doesn't free the memory for
+old threads. You can avoid this problem by starting @code{mysqld} with
+@code{-O thread_cache_size= 'max_connections +1'}. In most cases just
+using @code{-O thread_cache_size= 5'} will help a lot!
+
+If you are using gdb 4.17.x or above on Linux, you should install a
+@file{.gdb} file, with the following information, in your current
+directory:
+
+@example
+set print sevenbit off
+handle SIGUSR1 nostop noprint
+handle SIGUSR2 nostop noprint
+handle SIGWAITING nostop noprint
+handle SIGLWP nostop noprint
+handle SIGPIPE nostop
+handle SIGALRM nostop
+handle SIGHUP nostop
+handle SIGTERM nostop noprint
+@end example
+
+If you have problems debugging threads with gdb, you should download
+gdb 5.x and try this instead. The new gdb version has very improved
+thread handling!
+
+Here follows an example how to debug mysqld:
+
+@example
+shell> gdb /usr/local/libexec/mysqld
+gdb> run
+...
+back # Do this when mysqld crashes
+info locals
+up
+info locals
+up
+...
+(until you get some information about local variables)
+
+quit
+@end example
+
+Include the above output in a mail generated with @code{mysqlbug} and
+mail this to @code{mysql@@lists.mysql.com}.
+
+If @code{mysqld} hangs you can try to use some system tools like
+@code{strace} or @code{/usr/proc/bin/pstack} to examine where
+@code{mysqld} has hung.
+
+If @code{mysqld} starts to eat up CPU or memory or if it ``hangs'', you
+can use @code{mysqladmin processlist status} to find out if someone is
+executing a query that takes a long time. It may be a good idea to
+run @code{mysqladmin -i10 processlist status} in some window if you are
+experiencing performance problems or problems when new clients can't connect.
+
+If @code{mysqld} dies or hangs, you should start @code{mysqld} with
+@code{--log}. When @code{mysqld} dies again, you can check in the log
+file for the query that killed @code{mysqld}. Note that before starting
+@code{mysqld} with @code{--log} you should check all your tables with
+@code{myisamchk}. @xref{Maintenance}.
+
+If you are using a log file, @code{mysqld --log}, you should check the
+'hostname' log files, that you can find in the database directory, for
+any queries that could cause a problem. Try the command @code{EXPLAIN}
+on all @code{SELECT} statements that takes a long time to ensure that
+mysqld are using indexes properly. @xref{EXPLAIN, , @code{EXPLAIN}}. You
+should also test complicated queries that didn't complete within the
+@code{mysql} command line tool.
+
+If you find the text @code{mysqld restarted} in the error log file (normally
+named @file{hostname.err}) you have probably found a query that causes
+@code{mysqld} to fail. If this happens you should check all your tables with
+@code{myisamchk} (@pxref{Maintenance}), and test the queries in the
+@strong{MySQL} log files to see if one doesn't work. If you find such a query,
+try first upgrading to the newest @strong{MySQL} version. If this doesn't
+help and you can't find anything in the @code{mysql} mail archive, you should
+report the bug to @email{mysql@@lists.mysql.com}. Links to mail archives are
+available online at the @uref{http://www.mysql.com/documentation/, @strong{MySQL}
+documentation page}.
+
+If you get corrupted tables or if @code{mysqld} always fails after some
+update commands, you can test if this bug is reproducible by doing the
+following:
+
+@itemize @bullet
+@item
+Stop the mysqld daemon (with @code{mysqladmin shutdown})
+@item
+Check all tables with @code{myisamchk -s database/*.MYI}. Repair any
+wrong tables with @code{myisamchk -r database/table.MYI}.
+@item
+Start @code{mysqld} with @code{--log-update}. @xref{Update log}.
+@item
+When you have gotten a crashed table, stop the @code{mysqld server}.
+@item
+Restore the backup.
+@item
+Restart the @code{mysqld} server @strong{without} @code{--log-update}
+@item
+Re-execute the commands with @code{mysql < update-log}. The update log
+is saved in the @strong{MySQL} database directory with the name
+@code{your-hostname.#}.
+@item
+If the tables are corrupted again, you have found reproducible bug
+in the @code{ISAM} code! FTP the tables and the update log to
+@uref{ftp://support.mysql.com/pub/mysql/secret} and we will fix this as soon as
+possible!
+@end itemize
+
+The command @code{mysqladmin debug} will dump some information about
+locks in use, used memory and query usage to the mysql log file. This
+may help solve some problems. This command also provides some useful
+information even if you haven't compiled @strong{MySQL} for debugging!
+
+If the problem is that some tables are getting slower and slower you
+should try to optimize the table with @code{OPTIMIZE TABLE} or
+@code{myisamchk}. @xref{Maintenance}. You should also check the slow
+queries with @code{EXPLAIN}.
+
+You should also read the OS-specific section in this manual for
+problems that may be unique to your environment.
+@xref{Source install system issues}.
+
+@findex DBI->trace
+@findex trace DBI method
+@tindex DBI_TRACE environment variable
+@tindex Environment variable, DBI_TRACE
+If you are using the Perl @code{DBI} interface, you can turn on
+debugging information by using the @code{trace} method or by
+setting the @code{DBI_TRACE} environment variable.
+@xref{Perl DBI Class, , Perl @code{DBI} Class}.
+
+@node Debugging client, The DBUG package, Debugging server, Porting
+@appendixsec Debugging a MySQL client
+
+To be able to debug a @strong{MySQL} client with the integrated debug package,
+you should configure @strong{MySQL} with @code{--with-debug}.
+@xref{configure options}.
+
+@tindex MYSQL_DEBUG environment variable
+@tindex Environment variable, MYSQL_DEBUG
+Before running a client, you should set the @code{MYSQL_DEBUG} environment
+variable:
+
+@example
+shell> MYSQL_DEBUG=d:t:O,/tmp/client.trace
+shell> export MYSQL_DEBUG
+@end example
+
+This causes clients to generate a trace file in @file{/tmp/client.trace}.
+
+If you have problems with your own client code, you should attempt to
+connect to the server and run your query using a client that is known to
+work. Do this by running @code{mysql} in debugging mode (assuming you
+have compiled @strong{MySQL} with debugging on):
+
+@example
+shell> mysql --debug=d:t:O,/tmp/client.trace
+@end example
+
+This will provide useful information in case you mail a bug report.
+@xref{Bug reports}.
+
+If your client crashes at some 'legal' looking code, you should check
+that your @file{mysql.h} include file matches your mysql library file.
+A very common mistake is to use an old @file{mysql.h} file from an old
+@strong{MySQL} installation with new @strong{MySQL} library.
+
+
+@node The DBUG package, Locking methods, Debugging client, Porting
+@appendixsec The DBUG package.
+
+The @strong{MySQL} server and most @strong{MySQL} clients are compiled
+with the DBUG package originally made by Fred Fish. When one has configured
+@strong{MySQL} for debugging, this package makes it possible to get a trace
+file of what the program is debugging.
+
+One uses the debug package by invoking the program with the
+@code{--debug="..."} or the @code{-#...} option.
+
+The debug control string is a sequence of colon separated fields
+as follows:
+
+@example
+<field_1>:<field_2>:...:<field_N>
+@end example
+
+Each field consists of a mandatory flag character followed by
+an optional "," and comma separated list of modifiers:
+
+@example
+flag[,modifier,modifier,...,modifier]
+@end example
+
+The currently recognized flag characters are:
+
+@multitable @columnfractions .1 .9
+@item d @tab Enable output from DBUG_<N> macros for for the current state. May be followed by a list of keywords which selects output only for the DBUG macros with that keyword. A empty list of keywords implies output for all macros.
+@item D @tab Delay after each debugger output line. The argument is the number of tenths of seconds to delay, subject to machine capabilities. I.E. @code{-#D,20} is delay two seconds.
+@item f tab Limit debugging and/or tracing, and profiling to the list of named functions. Note that a null list will disable all functions. The appropriate "d" or "t" flags must still be given, this flag only limits their actions if they are enabled.
+@item F @tab Identify the source file name for each line of debug or trace output.
+@item i @tab Identify the process with the pid or thread id for each line of debug or trace output.
+@item g @tab Enable profiling. Create a file called 'dbugmon.out' containing information that can be used to profile the program. May be followed by a list of keywords that select profiling only for the functions in that list. A null list implies that all functions are considered.
+@item L @tab Identify the source file line number for each line of debug or trace output.
+@item n @tab Print the current function nesting depth for each line of debug or trace output.
+@item N @tab Number each line of dbug output.
+@item o @tab Redirect the debugger output stream to the specified file. The default output is stderr.
+@item O @tab As @code{O} but the file is really flushed between each write. When neaded the file is closed and reopened between each write.
+@item p @tab Limit debugger actions to specified processes. A process must be identified with the DBUG_PROCESS macro and match one in the list for debugger actions to occur.
+@item P @tab Print the current process name for each line of debug or trace output.
+@item r @tab When pushing a new state, do not inherit the previous state's function nesting level. Useful when the output is to start at the left margin.
+@item S @tab Do function _sanity(_file_,_line_) at each debugged function until _sanity() returns something that differs from 0. (Mostly used with safemalloc to find memory leaks)
+@item t @tab Enable function call/exit trace lines. May be followed by a list (containing only one modifier) giving a numeric maximum trace level, beyond which no output will occur for either debugging or tracing macros. The default is a compile time option.
+@end multitable
+
+Some examples of debug control strings which might appear on a shell
+command line (the "-#" is typically used to introduce a control string
+to an application program) are:
+
+@example
+-#d:t
+-#d:f,main,subr1:F:L:t,20
+-#d,input,output,files:n
+-#d:t:i:O,\\mysqld.trace
+@end example
+
+In @strong{MySQL}, common tags to print (with the @code{d} option) are:
+@code{enter},@code{exit},@code{error},@code{warning},@code{info} and
+@code{loop}.
+
+@node Locking methods, RTS-threads, The DBUG package, Porting
+@appendixsec Locking methods
+
+Currently MySQL only supports table locking for
+@code{ISAM}/@code{MyISAM} and @code{HEAP} tables and page level locking
+for @code{BDB} tables. @xref{Internal locking}. With @code{MyISAM}
+tables one can freely mix @code{INSERT} and @code{SELECT} without locks
+(@code{Versioning}).
+
+Some database users claim that @strong{MySQL} cannot support near the
+number of concurrent users because it lacks row-level locking. This is
+a may be true for some specific applications, but is' not generally
+true. As always this depends totally on what the application does and what is the access/update pattern of the data.
+
+Pros for row locking:
+
+@itemize @bullet
+@item
+Fewer lock conflicts when accessing different rows in many threads.
+@item
+Less changes for rollbacks.
+@item
+Makes it possbile to lock a single row a long time.
+@end itemize
+
+Cons:
+
+@itemize @bullet
+@item
+Takes more memory than page level or table locks.
+@item
+Is slower than page level or table locks when used one a big part of the table,
+because one has to do many more locks.
+@item
+Is definitely much worse than other locks if you do often do @code{GROUP
+BY} on a large part of the data or if one has to often scan the whole table.
+@item
+With higher level locks one can also more easily support locks of
+different types to tune the application as the lock overhead is less
+notable as for row level locks.
+@end itemize
+
+Table locks are superior to page level / row level locks in the
+following cases:
+
+@itemize @bullet
+@item
+Mostly reads
+@item
+Read and updates on strict keys; This is where one updates or deletes
+a row that can be fetched with one key read:
+@example
+UPDATE table_name SET column=value WHERE unique_key#
+DELETE FROM table_name WHERE unique_key=#
+@end example
+@item
+@code{SELECT} combined with @code{INSERT} (and very few @code{UPDATE}'s
+and @code{DELETE}'s.
+@item
+Many scans / @code{GROUP BY} on the whole table without any writers.
+@end itemize
+
+Other options than row / page level locking:
+
+Versioning (like we use in MySQL for concurrent inserts) where you can
+have one writer at the same time as many readers. This means that the
+database/table supports different views for the data depending on when
+one started to access it. Other names for this are time travel, copy
+on write or copy on demand.
+
+Copy on demand is in many case much better than page or row level
+locking; The worst case does however use much more memory than
+when using normal locks.
+
+Instead of using row level locks one can use application level locks.
+(Like get_lock/release_lock in @strong{MySQL}). This works of course
+only in well-behaved applications.
+
+In many cases one can do an educated guess which locking type is best
+for the application but generally it's very hard to say that a given
+lock type is better than another; Everything depends on the application
+and different part of the application may require different lock types.
+
+Here follows some tips about locking in @strong{MySQL}:
+
+On web application most applications do lots of selects, very few
+deletes, updates mainly on keys and inserts in some specific tables.
+The base @strong{MySQL} setup is VERY tuned for this.
+
+Concurrent users is not a problem if one doesn't mix updates and selects
+that needs to examine many rows in the same table.
+
+If one mix a insert and deletes on the same table then @code{INSERT DELAY}
+may be of great help.
+
+One can also use @code{LOCK TABLES} to speed up things (many updates within
+a single lock is much faster than updates without locks). Splitting
+thing to different tables will also helps.
+
+If you get speed problems with the table locks in @strong{MySQL}, you
+may be able to solve these to convert some of your tables to @code{BDB} tables.
+@xref{BDB}.
+
+The optimization section in the manual covers a lot of different aspects of
+how to tune ones application. @xref{Tips}.
+
+@node RTS-threads, Thread packages, Locking methods, Porting
+@appendixsec Comments about RTS threads
+
+I have tried to use the RTS thread packages with @strong{MySQL} but
+stumbled on the following problems:
+
+They use an 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. See @file{mysys/my_pthread.c} for more info.
+
+At least the following should be changed:
+
+@code{pthread_get_specific} should use one argument.
+@code{sigwait} should take two arguments.
+A lot of functions (at least @code{pthread_cond_wait},
+@code{pthread_cond_timedwait})
+should return the error code on error. Now they return -1 and set @code{errno}.
+
+Another problem is that user-level threads use the @code{ALRM} signal and this
+aborts a lot of functions (@code{read}, @code{write}, @code{open}...).
+@strong{MySQL} should do a retry on interrupt on all of these but it is
+not that easy to verify it.
+
+The biggest unsolved problem is the following:
+
+To get thread-level alarms I changed @file{mysys/thr_alarm.c} to wait between
+alarms with @code{pthread_cond_timedwait()}, but this aborts with error
+@code{EINTR}. I tried to debug the thread library as to why this happens,
+but couldn't find any easy solution.
+
+If someone wants to try @strong{MySQL} with RTS threads I suggest the
+following:
+
+@itemize @bullet
+@item
+Change functions @strong{MySQL} uses from the thread library to POSIX.
+This shouldn't take that long.
+@item
+Compile all libraries with the @code{-DHAVE_rts_threads}.
+@item
+Compile @code{thr_alarm}.
+@item
+If there are some small differences in the implementation, they may be fixed
+by changing @file{my_pthread.h} and @file{my_pthread.c}.
+@item
+Run @code{thr_alarm}. If it runs without any ``warning'', ``error'' or aborted
+messages, you are on the right track. Here follows a successful run on
+Solaris:
+@example
+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 Slept for 1 (1) sec
+Thread: 6 Waiting
+process_alarm
+process_alarm
+thread_alarm
+Thread: 6 Slept for 2 (2) sec
+Thread: 6 Simulation of no alarm needed
+Thread: 6 Slept for 0 (3) sec
+Thread: 6 Waiting
+process_alarm
+process_alarm
+thread_alarm
+Thread: 6 Slept for 4 (4) sec
+Thread: 6 Waiting
+process_alarm
+thread_alarm
+Thread: 5 Slept for 10 (10) sec
+Thread: 5 Waiting
+process_alarm
+process_alarm
+thread_alarm
+Thread: 6 Slept for 5 (5) sec
+Thread: 6 Waiting
+process_alarm
+process_alarm
+
+...
+thread_alarm
+Thread: 5 Slept for 0 (1) sec
+end
+@end example
+@end itemize
+
+@node Thread packages, , RTS-threads, Porting
+@appendixsec Differences between different thread packages
+
+@strong{MySQL} is very dependent on the thread package used. So when
+choosing a good platform for @strong{MySQL}, the thread package is very
+important.
+
+There are at least three types of thread packages:
+
+@itemize @bullet
+@item
+User threads in a single process. Thread switching is managed with
+alarms and the threads library manages all non-thread-safe functions
+with locks. Read, write and select operations 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-pthreads, FSU Pthreads and RTS threads). In some
+environments (for example, SCO), all system calls are thread-safe so the
+mapping can be done very easily (FSU Pthreads 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-pthreads and sockets). Thread
+scheduling isn't always optimal.
+@item
+User threads in separate processes. Thread switching is done by the
+kernel and all data are 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 you must kill them all before restarting. Thread switching is
+somewhat expensive.
+@item
+Kernel threads. Thread switching is handled by the thread library or the
+kernel and is very fast. Everything is done in one process, but on some
+systems, @code{ps} may show the different threads. If one thread aborts, the
+whole process aborts. Most system calls are thread-safe and should
+require very little overhead. Solaris, HP-UX, AIX and OSF1 have kernel
+threads.
+@end itemize
+
+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''.
+
+@node Regexp, Unireg, Porting, Top
+@appendix Description of MySQL regular expression syntax
+
+A regular expression (regex) is a powerful way of specifying a complex search.
+
+@strong{MySQL} uses Henry Spencer's implementation of regular
+expressions, which is aimed to conform to POSIX
+1003.2. @strong{MySQL} uses the extended version.
+
+This is a simplistic reference that skips the details. To get more exact
+information, see Henry Spencer's @code{regex(7)} manual page that is
+included in the source distribution. @xref{Credits}.
+
+A regular expression describes a set of strings. The simplest regexp is
+one that has no special characters in it. For example, the regexp
+@code{hello} matches @code{hello} and nothing else.
+
+Non-trivial regular expressions use certain special constructs so that
+they can match more than one string. For example, the regexp
+@code{hello|word} matches either the string @code{hello} or the string
+@code{word}.
+
+As a more complex example, the regexp @code{B[an]*s} matches any of the
+strings @code{Bananas}, @code{Baaaaas}, @code{Bs} and any other string
+starting with a @code{B}, ending with an @code{s}, and containing any
+number of @code{a} or @code{n} characters in between.
+
+A regular expression may use any of the following special
+characters/constructs:
+@table @code
+@item ^
+Match the beginning of a string.
+@example
+mysql> select "fo\nfo" REGEXP "^fo$"; -> 0
+mysql> select "fofo" REGEXP "^fo"; -> 1
+@end example
+@item $
+Match the end of a string.
+@example
+mysql> select "fo\no" REGEXP "^fo\no$"; -> 1
+mysql> select "fo\no" REGEXP "^fo$"; -> 0
+@end example
+@item .
+Match any character (including newline).
+@example
+mysql> select "fofo" REGEXP "^f.*"; -> 1
+mysql> select "fo\nfo" REGEXP "^f.*"; -> 1
+@end example
+@item a*
+Match any sequence of zero or more @code{a} characters.
+@example
+mysql> select "Ban" REGEXP "^Ba*n"; -> 1
+mysql> select "Baaan" REGEXP "^Ba*n"; -> 1
+mysql> select "Bn" REGEXP "^Ba*n"; -> 1
+@end example
+@item a+
+Match any sequence of one or more @code{a} characters.
+@example
+mysql> select "Ban" REGEXP "^Ba+n"; -> 1
+mysql> select "Bn" REGEXP "^Ba+n"; -> 0
+@end example
+@item a?
+Match either zero or one @code{a} character.
+@example
+mysql> select "Bn" REGEXP "^Ba?n"; -> 1
+mysql> select "Ban" REGEXP "^Ba?n"; -> 1
+mysql> select "Baan" REGEXP "^Ba?n"; -> 0
+@end example
+@item de|abc
+Match either of the sequences @code{de} or @code{abc}.
+@example
+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
+@end example
+@item (abc)*
+Match zero or more instances of the sequence @code{abc}.
+@example
+mysql> select "pi" REGEXP "^(pi)*$"; -> 1
+mysql> select "pip" REGEXP "^(pi)*$"; -> 0
+mysql> select "pipi" REGEXP "^(pi)*$"; -> 1
+@end example
+@item @{1@}
+@itemx @{2,3@}
+The is a more general way of writing regexps that match many
+occurrences of the previous atom.
+@table @code
+@item a*
+Can be written as @code{a@{0,@}}.
+@item a+
+Can be written as @code{a@{1,@}}.
+@item a?
+Can be written as @code{a@{0,1@}}.
+@end table
+To be more precise, an atom followed by a bound containing one integer
+@code{i} and no comma matches a sequence of exactly @code{i} matches of
+the atom. An atom followed by a bound containing one integer @code{i}
+and a comma matches a sequence of @code{i} or more matches of the atom.
+An atom followed by a bound containing two integers @code{i} and
+@code{j} matches a sequence of @code{i} through @code{j} (inclusive)
+matches of the atom.
+
+Both arguments must @code{0 >= value <= RE_DUP_MAX (default 255)}.
+If there are two arguments, the second must be greater than or equal to the
+first.
+@item [a-dX]
+@itemx [^a-dX]
+Matches
+any character which is (or is not, if ^ is used) either @code{a}, @code{b},
+@code{c}, @code{d} or @code{X}. To include a literal @code{]} character,
+it must immediately follow the opening bracket @code{[}. To include a
+literal @code{-} character, it must be written first or last. So
+@code{[0-9]} matches any decimal digit. Any character that does not have
+a defined meaning inside a @code{[]} pair has no special meaning and
+matches only itself.
+@example
+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
+@end example
+@item [[.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 @code{ch}
+collating element, then the regular expression @code{[[.ch.]]*c} matches the
+first five characters of @code{chchcc}.
+
+@item [=character_class=]
+An equivalence class, standing for the sequences of characters of all
+collating elements equivalent to that one, including itself.
+
+For example, if @code{o} and @code{(+)} are the members of an
+equivalence class, then @code{[[=o=]]}, @code{[[=(+)=]]}, and
+@code{[o(+)]} are all synonymous. An equivalence class may not be an
+endpoint of a range.
+
+@item [:character_class:]
+Within a bracket expression, the name of a character class enclosed in
+@code{[:} and @code{:]} stands for the list of all characters belonging
+to that class. Standard character class names are:
+
+@multitable @columnfractions .33 .33 .33
+@item alnum @tab digit @tab punct
+@item alpha @tab graph @tab space
+@item blank @tab lower @tab upper
+@item cntrl @tab print @tab xdigit
+@end multitable
+
+These stand for the character classes defined in the @code{ctype(3)} manual
+page. A locale may provide others. A character class may not be used as an
+endpoint of a range.
+@example
+mysql> select "justalnums" REGEXP "[[:alnum:]]+"; -> 1
+mysql> select "!!" REGEXP "[[:alnum:]]+"; -> 0
+@end example
+
+@item [[:<:]]
+@itemx [[:>:]]
+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 @code{ctype(3)}) or an underscore
+(@code{_}).
+@example
+mysql> select "a word a" REGEXP "[[:<:]]word[[:>:]]"; -> 1
+mysql> select "a xword a" REGEXP "[[:<:]]word[[:>:]]"; -> 0
+@end example
+@end table
+
+@example
+mysql> select "weeknights" REGEXP "^(wee|week)(knights|nights)$"; -> 1
+@end example
+
+@node Unireg, GPL license, Regexp, Top
+@appendix What is Unireg?
+
+Unireg is our tty interface builder, but it uses a low level connection
+to our ISAM (which is used by @strong{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:
+
+@itemize @bullet
+@item
+One table viewer with updates/browsing.
+@item
+Multi table viewer (with one scrolling region).
+@item
+Table creator. (With lots of column tags you can't create with @strong{MySQL})
+This is WYSIWYG (for a tty). You design a screen and Unireg prompts for
+the column specification.
+@item
+Report generator.
+@item
+A lot of utilities (quick import/export of tables to/from text files,
+analysis of table contents...).
+@item
+Powerful multi-table updates (which we use a lot) with a BASIC-like
+language with LOTS of functions.
+@item
+Dynamic languages (at present in Swedish and Finnish). If somebody wants
+an English version there are a few files that would have to be translated.
+@item
+The ability to run updates interactively or in a batch.
+@item
+Emacs-like key definitions with keyboard macros.
+@item
+All this in a binary of 800K.
+@item
+The @code{convform} utility. Converts @file{.frm} and text files between
+different character sets.
+@item
+The @code{myisampack} utility. Packs an ISAM table (makes it 50-80%
+smaller). The table can be read by @strong{MySQL} like an ordinary
+table. Only one record has to be decompressed per access. Cannot handle
+@code{BLOB} or @code{TEXT} columns or updates (yet).
+@end itemize
+
+We update most of our production databases with the Unireg interface and
+serve web pages through @strong{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: SunOS 4.x, Solaris, Linux, HP-UX, ICL Unix, DNIX, SCO and
+MS-DOS.
+
+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 @strong{MySQL}). Usually we compile the binary for the
+customer at their site.
+
+All new development is concentrated to @strong{MySQL}.
+
+@page
+@c This node name is special
+@node GPL license, LGPL license, Unireg, Top
+@appendix GNU General Public License
+
+@example
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+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. However, as a
+special exception, 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.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+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.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+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.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 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.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+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.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+@end example
+
+@page
+@node LGPL license, Function Index, GPL license, Top
+@appendix GNU Library General Public License
+
+@example
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+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.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+@end example
+
+@node Function Index, Concept Index, LGPL license, Top
+@unnumbered SQL command, type and function index
+
+@printindex fn
+
+@page
+@node Concept Index, , Function Index, Top
+@unnumbered Concept Index
+
+@printindex cp
+
+@summarycontents
+@contents
+
+@bye
diff --git a/Docs/myisam.txt b/Docs/myisam.txt
new file mode 100644
index 00000000000..e0b56e79548
--- /dev/null
+++ b/Docs/myisam.txt
@@ -0,0 +1,901 @@
+#.# mi_changed()
+
+int mi_is_changed(MI_INFO *mip)
+
+#.#.1 Description
+
+Reports whether any changes have occurred to the MyISAM table associated with mip.
+
+For information only, I notice that mi_changed() is a wrapper around this: (_mi_readinfo(info,F_RDLCK,1)).
+
+#.#.2 Return values
+
+Zero if the table has not changed. Non-zero (-1) if the table has changed.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+if( mi_changed( mip )) printf( "file has changed" );
+====================
+#.# mi_close()
+
+int mi_close( MI_INFO *mip )
+
+#.#.1 Description
+
+Closes the MyISAM table associated with mip, a structure created by mi_open().
+Any locks on that file pointer are released.
+The MI_INFO structure mip is released.
+See also mi_panic() which can be used to close all open MyISAM files.
+mip is a pointer to the MI_INFO returned by mi_open().
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+result = mi_close(mip);
+====================
+#.# mi_create()
+
+int mi_create( const char *name, uint keys, MI_KEYDEF *keydefs,
+ uint columns, MI_COLUMNDEF *recinfo,
+ uint uniques, MI_UNIQUEDEF *uniquedefs,
+ MI_CREATE_INFO *ci, uint flags )
+
+#.#.1 Description
+
+Creates a new MyISAM table.
+Documentation for this function is not complete because I am not using mi_create directly.
+Because all our tables are used with MySQL, I create new tables using SQL "CREATE TABLE" via the C API.
+See MySQL Appendix B "Choosing a table type".
+MyISAM allows about 32 indexes. However the official MySQL limit is 16 until MySQL 4.0.
+
+The parameters are specified as follows:
+name The file pathname, excluding the suffixes.
+keys Number of indexes.
+keydefs A MI_KEYDEF structure containing key definitions.
+HA_KEYTYPE_END=0
+HA_KEYTYPE_TEXT=1, /* Key is sorted as letters */
+HA_KEYTYPE_BINARY=2, /* Key is sorted as unsigned chars
+HA_KEYTYPE_SHORT_INT=3,
+HA_KEYTYPE_LONG_INT=4,
+HA_KEYTYPE_FLOAT=5,
+HA_KEYTYPE_DOUBLE=6,
+HA_KEYTYPE_NUM=7, /* Not packed num with pre-space *
+HA_KEYTYPE_USHORT_INT=8,
+HA_KEYTYPE_ULONG_INT=9,
+HA_KEYTYPE_LONGLONG=10,
+HA_KEYTYPE_ULONGLONG=11,
+HA_KEYTYPE_INT24=12,
+HA_KEYTYPE_UINT24=13,
+HA_KEYTYPE_INT8=14,
+HA_KEYTYPE_VARTEXT=15, /* Key is sorted as letters */
+HA_KEYTYPE_VARBINARY=16 /* Key is sorted as unsigned chars
+columns The number of columns.
+recinfo A MI_COLUMNDEF structure containing column definitions.
+uniques The number of unique indexes.
+uniquedefs A MI_UNIQUEDEF structure containing unique index definitions.
+ci A MI_CREATE_INFO structure containing column definitions.
+flags a pointer to the record buffer that will contain the row.
+
+#.#.2 Return values
+
+Zero if the create is successful. Non-zero if an error occurs.
+
+#.#.3 Errors
+
+HA_WRONG_CREATE_OPTION
+ means that some of the arguments was wrong.
+appart from the above one can get any unix error that one can get from open(), write() or close().
+
+#.#.4 Examples
+
+if (mi_create(fn_format(name,filename,"",MI_NAME_IEXT, 4+ (opt_follow_links ? 16 : 0)),
+ share.base.keys - share.state.header.uniques, keyinfo, share.base.fields, recdef,
+ share.state.header.uniques, uniquedef, &create_info, HA_DONT_TOUCH_DATA))
+====================
+#.# mi_delete()
+
+int mi_delete(MI_INFO *mip, const byte *buf)
+
+#.#.1 Description
+
+Removes a row from a MyISAM table.
+
+mip is an MI_INFO pointer to the open handle.
+buf is the buffer containing the row that is to be deleted.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+EACCES
+File was opened read-only.
+HA_ERR_KEY_NOT_FOUND
+No database read
+HA_ERR_RECORD_CHANGED
+The buffer contents were different to the actual row contents.
+HA_ERR_CRASHED
+The indexing has crashed.
+
+#.#.4 Examples
+
+if (mi_delete(file,read_record))
+====================
+#.# mi_delete_all()
+
+int mi_delete_all_rows(MI_INFO *mip)
+#.#.1 Description
+
+Removes ALL rows from a MyISAM table.
+This only clears the status information. The files are not truncated.
+
+mip is an MI_INFO pointer to the open handle.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+EACCES
+File was opened read-only.
+
+#.#.4 Examples
+
+error = mi_delete_all( mip );
+====================
+#.# mi_extra()
+
+int mi_extra(MI_INFO *info, enum ha_extra_function function)
+
+#.#.1 Description
+
+Controls some special MyISAM modes.
+
+The function parameter can be:
+ HA_EXTRA_NORMAL=0 Optimize for space (def)
+HA_EXTRA_QUICK=1 Optimize for speed
+HA_EXTRA_RESET=2 Reset database to after open
+HA_EXTRA_CACHE=3 Cash record in HA_rrnd()
+HA_EXTRA_NO_CACHE=4 End cacheing of records (def)
+HA_EXTRA_NO_READCHECK=5 No readcheck on update
+HA_EXTRA_READCHECK=6 Use readcheck (def)
+HA_EXTRA_KEYREAD=7 Read only key to database
+HA_EXTRA_NO_KEYREAD=8 Normal read of records (def)
+HA_EXTRA_NO_USER_CHANGE=9 No user is allowed to write
+HA_EXTRA_KEY_CACHE=10
+HA_EXTRA_NO_KEY_CACHE=11
+HA_EXTRA_WAIT_LOCK=12 Wait until file is avalably (def)
+HA_EXTRA_NO_WAIT_LOCK=13 If file is locked, return quickly
+HA_EXTRA_WRITE_CACHE=14 Use write cache in ha_write()
+HA_EXTRA_FLUSH_CACHE=15 flush write_record_cache
+HA_EXTRA_NO_KEYS=16 Remove all update of keys
+HA_EXTRA_KEYREAD_CHANGE_POS=17 Keyread, but change pos
+xxxxchk -r must be used
+HA_EXTRA_REMEMBER_POS=18 Remember pos for next/prev
+HA_EXTRA_RESTORE_POS=19
+HA_EXTRA_REINIT_CACHE=20 init cache from current record
+HA_EXTRA_FORCE_REOPEN=21 Datafile have changed on disk
+HA_EXTRA_FLUSH Flush tables to disk
+HA_EXTRA_NO_ROWS Don't write rows
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+====================
+#.# mi_make_application_key()
+
+void mi_make_application_key(register MI_INFO *mip, uint keynr, uchar *key, const byte *record)
+
+#.#.1 Description
+
+Construct a key string for the given index, from the provided record buffer.
+Monty wrote this function to: "to create an external key for an application from your record. It should work for all keys except BLOB and true VARCHAR (not supported by MySQL yet), but I don't think you have either of these!" He just wrote it, so I expect it to included in releases from about 3.23.15. ??
+
+The parameters are:
+A MI_INFO pointer mip.
+The index number keynr.
+The buffer to contain the formatted key string key.
+The record buffer record.
+
+#.#.2 Return values
+
+The byte length of the created key string.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+uint new_length=_mi_make_application_key(info,i,new_key,newrec);
+====================
+#.# mi_open()
+
+MI_INFO *mi_open( const char *name, int mode, uint handle_locking )
+
+#.#.1 Description
+
+Opens a MyISAM file for processing.
+mi_open() returns a MI_INFO structure pointer that you must use in subsequent operations on the MyISAM file. MI_INFO structures are defined in "myisam/myisamdef.h", which is included in your program via your include myisam.h - used by both MyISAM and MySQL.
+The name parameter must contain a null-terminated string without an extension, which is the filename of the MyISAM file to be processed.
+There is no automatic positioning nor key selection.
+Caution! It is extremely important to close MyISAM files after processing has finished, especially on operating systems without file-locking system calls. Failure to close MyISAM files using mi_close() or mi_panic() leaves the files locked on systems without these system calls.
+
+name Is the name of the file.
+mode Is the access mode parameter. Use one of the following access mode parameters:
+O_RDONLY to open for input only.
+O_RDWR opens the file for output.
+O_SHARE opens the file for both input and output. When used, O_SHARE should be added to O_RDONLY and O_RDWR.
+handle_locking is the locking mode parameter. Select from the following:
+HA_OPEN_ABORT_IF_LOCKED (0) exit with error if database is locked
+HA_OPEN_WAIT_IF_LOCKED (1) wait if database is locked
+HA_OPEN_IGNORE_IF_LOCKED (2) continue, but count-vars in st_i_info may be wrong. count-vars are automatically fixed after next isam request.
+
+#.#.2 Return values
+
+A pointer to MI_INFO for successfully open file. NULL if unsuccessful, when my_errno will contain the error code.
+
+#.#.3 Errors
+
+HA_ERR_OLD_FILE
+wrong options
+HA_ERR_CRASHED
+wrong header
+HA_ERR_UNSUPPORTED
+too many keys or keys too long
+HA_ERR_END_OF_FILE
+empty file?
+MY_FILE_ERROR
+?
+EACCES
+cannot open in write mode
+ENOMEM
+not enough memory
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+pfm = mi_open("/D1/adir/perform",O_SHARE | O_RDONLY, HA_OPEN_ABORT_IF_LOCKED);
+====================
+#.# mi_panic()
+
+int mi_panic( enum ha_panic_function flag )
+
+#.#.1 Description
+
+mi_panic() is used to close any MyISAM files before exiting, or to safeguard file updates when using a shell.
+The flag parameter specifies the function and can be:
+HA_PANIC_CLOSE Close all databases (MyISAM files).
+HA_PANIC_WRITE Unlock and write status, flushing all buffers to disk.
+HA_PANIC_READ Lock and read key info per HA_PANIC_WRITE.
+
+The CLOSE function also writes buffers before it closes and turns logging off by closing the log file..
+See also my_end(), a debugging function.
+One use is to do a WRITE, use a shell to run myisamchk, then do a READ.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+result = mi_panic(HA_PANIC_CLOSE);
+====================
+#.# mi_position()
+
+my_off_t mi_position(MI_INFO *mip)
+
+#.#.1 Description
+
+Gets the byte position in the file of the last record read.
+
+mip is an MI_INFO pointer to the open handle.
+
+#.#.2 Return values
+
+Byte position if successful. Zero if an error occurred. ??
+
+#.#.3 Errors
+
+HA_OFFSET_ERROR
+if there wasn't any active row.
+
+#.#.4 Examples
+
+currentpos = mi_position( mip );
+====================
+#.# mi_rfirst()
+
+int mi_rfirst(MI_INFO *mip , byte *buf, int inx)
+
+#.#.1 Description
+
+Reads the first row in the MyISAM file according to the specified index.
+If one want's to read rows in physical sequences, then one should instead use mi_scan() or mi_rrnd().
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+Inx is the index (key) number, which must be the same as currently selected.
+
+mi_rfirst() works by setting the current position mip->lastpos to HA_OFFSET_ERROR (undefined) then calling mi_rnext().
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_END_OF_FILE
+End of file
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+error = mi_rfirst( mip, buffer, keynum);
+====================
+#.# mi_rkey()
+
+int mi_rkey(MI_INFO *mip, byte *buf, int inx, const byte *key, uint key_len, enum ha_rkey_function search_flag)
+
+#.#.1 Description
+
+Reads the next row after the last row read, using the current index.
+If one want's to read rows in physical sequences, then one should instead use mi_scan() or mi_rrnd().
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+Inx is the index (key) number, which must be the same as currently selected.
+
+If (mip->lastpos) is HA_OFFSET_ERROR (undefined) then mi_rnext() gives the first row.
+If you specify a different index number than the last read used, you will get an error.
+If the last (current) row has been changed since we read it, mi_rnext() will reposition from the position where that row WAS, not where it is now. (This behaviour is similar to CISAM and better than used in Codebase.)
+
+mi_extra(HA_EXTRA_KEYREAD) can be called first, to cause mi_rkey to read the key but not the record. Then call mi_extra(HA_EXTRA_NO_KEYREAD) to resume normal behaviour.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_END_OF_FILE
+End of file
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+error = mi_rnext( mip, buffer, keynum );
+====================
+#.# mi_rlast()
+
+int mi_rlast(MI_INFO *mip , byte *buf, int inx)
+
+#.#.1 Description
+
+Reads the last row in the MyISAM file according to the specified index.
+If one want's to read rows in physical sequences, then one should instead use mi_scan() or mi_rrnd().
+mip is an MI_INFO pointer to the open handle.
+buf is a pointer to the record buffer that will contain the row.
+Inx is the index (key) number, which must be the same as currently selected.
+
+mi_rlast() works by setting the current position (mip->lastpos) to HA_OFFSET_ERROR (undefined) then calling mi_rprev().
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_END_OF_FILE
+End of file
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+error = mi_rlast( mip, buffer, keynum);
+====================
+#.# mi_rnext()
+
+int mi_rnext(MI_INFO *mip , byte *buf, int inx )
+
+#.#.1 Description
+
+Reads the next row after the last row read, using the current index.
+If one want's to read rows in physical sequences, then one should instead use mi_scan() or mi_rrnd().
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+Inx is the index (key) number, which must be the same as currently selected.
+
+If (mip->lastpos) is HA_OFFSET_ERROR (undefined) then mi_rnext() gives the first row.
+If you specify a different index number than the last read used, you will get an error.
+If the last (current) row has been changed since we read it, mi_rnext() will reposition from the position where that row WAS, not where it is now. (This behaviour is similar to CISAM and better than used in Codebase.)
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_END_OF_FILE
+End of file
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+error = mi_rnext( mip, buffer, keynum );
+====================
+#.# mi_rrnd()
+
+int mi_rrnd( MI_INFO *mip , byte *buf, my_off_t filepos )
+
+#.#.1 Description
+
+Reads a row based on physical position.
+
+Position can be calculated from record number only when fixed record lengths are used:
+position = mip->s.pack.header_length + recnum * mip->s->base.reclength.
+If filepos= HA_OFFSET_ERROR then it reads the next row.
+And if (mip->lastpos == HA_OFFSET_ERROR) it reads the first row.
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+filepos is the byte position in the file of the required record.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_RECORD_DELETED
+A deleted record was read.
+HA_ERR_END_OF_FILE
+End of file.
+
+#.#.4 Examples
+
+error = mi_rrnd( mip, buffer, mip->nextpos );
+====================
+#.# mi_rprev()
+
+int mi_rprev(MI_INFO *mip , byte *buf, int inx)
+
+#.#.1 Description
+
+Reads the row previous to the last row read, using the current index.
+If one wants to read rows in physical sequences, then one should instead use mi_scan() or mi_rrnd().
+
+If (mip->lastpos) is HA_OFFSET_ERROR (undefined) then mi_rnext() gives the last row in the index.
+If you specify a different index number than the last read used, you will get an error.
+If the last (current) row has been changed since we read it, mi_rprev() will reposition from the position where that row WAS, not where it is now. This behaviour is similar to CISAM and better than used in Codebase.
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+Inx is the index (key) number, which must be the same as currently selected.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_END_OF_FILE
+End of file
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+error = mi_rprev( mip, buffer, keynum );
+====================
+#.# mi_rsame()
+
+int mi_rsame(MI_INFO *mip, byte *buf, int inx)
+
+#.#.1 Description
+
+Reads the current row to get its latest contents. This is useful to refresh the record buffer in case someone else has changed it.
+If inx is negative it reads by position. If inx is >= 0 it reads by key.
+With mi_rsame() one can switch to use any other index for the current row. This is good if you have a user application that lets the user do 'read-next' on a row. In this case, if the user want's to start scanning on another index, one simply has to do a mi_rsame() on the new index to activate this.
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+inx is the index (key) number, or a negative number to select read by position not index. Maybe the negative number has to be (-1) to achieve this behaviour.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_WRONG_INDEX
+an incorrect index number was supplied
+HA_ERR_KEY_NOT_FOUND
+info->lastpos was not defined, or the record was already deleted.
+
+#.#.4 Examples
+
+error = mi_rsame( m5mip, rec_ptr, keynum );
+====================
+#.# mi_scan()
+
+int mi_scan(MI_INFO *mip, byte *buf)
+
+#.#.1 Description
+
+Reads the next row by physical position.
+
+Deleted rows are bypassed.
+mi_scan() uses a function pointer "read_rnd" that uses either lower level static or dynamic read functions, positioning from mip->nextpos. Read_rnd is defined in mi_open() depending if the table is Static (read*static - see mi_statrec.c), Compressed (read*pack - see mi_packrec.c), or Space packed or Blobs (read*dynamic - see mi_dynrec.c).
+See also mi_scan_init() which initialises ready to mi_scan() through the whole table.
+
+mip is an MI_INFO pointer to the open handle.
+buf is the record buffer that will contain the row.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_END_OF_FILE
+End of file
+Otherwise one has probably got a fatal error like HA_ERR_CRASHED or some I-O related error from the Operating System.
+
+#.#.4 Examples
+
+error = mi_scan( mip, recbuff );
+====================
+#.# mi_scan_init()
+
+int mi_scan_init(MI_INFO *mip[SB1])
+
+#.#.1 Description
+
+Initialises ready to mi_scan() through all rows.
+
+mip is an MI_INFO pointer to the open handle.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+====================
+#.# mi_status()
+
+int mi_status(MI_INFO *mip, MI_ISAMINFO *x, uint flag)
+
+#.#.1 Description
+
+Gets information about the table.
+It is used to get/fill the MI_ISAMINFO struct with statistics data about the MySQL server. One can get information of the number of active rows, delete rows, file lengths...
+
+mip is an MI_INFO pointer to the open handle.
+flag is one of the following:
+HA_STATUS_POS Return position
+HA_STATUS_NO_LOCK Don't use external lock
+HA_STATUS_TIME Return update time
+HA_STATUS_CONST Return constants value
+HA_STATUS_VARIABLE
+HA_STATUS_ERRKEY
+HA_STATUS_AUTO
+
+#.#.2 Return values
+
+Zero.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+====================
+#.# mi_update()
+
+int mi_update( MI_INFO *mip, const byte *oldbuf, byte *newbuf)
+
+#.#.1 Description
+
+Updates the contents of the current record.
+By default you must supply an oldbuf record buffer with the current record contents. This is compared with the file as a guard in case someone else has changed the record in the meantime. *
+
+mip is an MI_INFO pointer to the open handle.
+oldbuf is the record buffer that contains the current record contents.
+newbuf is the record buffer that contains the new record contents.
+
+*Sometimes you might want to force an update without checking whether another user has changed the record since you last read it. This is somewhat dangerous, so it should ideally not be used. That can be accomplished by wrapping the mi_update() call in two calls to mi_extra(), using these functions:
+HA_EXTRA_NO_READCHECK=5 No readcheck on update
+HA_EXTRA_READCHECK=6 Use readcheck (def)
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+EACCES
+The file was opened for read-only access.
+HA_ERR_RECORD_CHANGED
+ When mi_update() read the current record contents before updating, it differed from oldbuf.
+HA_ERR_CRASHED
+Key could not be found ??
+HA_ERR_FOUND_DUPP_KEY
+HA_ERR_RECORD_FILE_FULL
+
+#.#.4 Examples
+
+error = mi_update( mip, oldbuf, newbuf );
+====================
+#.# mi_write()
+
+int mi_write( MI_INFO *mip, byte *record)
+
+#.#.1 Description
+
+Writes a row to a MyISAM table.
+
+mip is an MI_INFO pointer to the open handle.
+The record contents are supplied in buf record buffer.
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+HA_ERR_FOUND_DUPP_KEY
+A record already existed with a unique key same as this new record.
+HA_ERR_RECORD_FILE_FULL
+The error is given if you hit a system limit or if you try to create more rows in a table that you reserverd room for with mi_create().
+ENOSPC
+The disk is full.
+EACCES
+The file was opened for read-only access.
+
+#.#.4 Examples
+
+error = mi_write( m5mip, recbuf );
+====================
+#.# my_end()
+
+void my_end(int infoflag)
+
+#.#.1 Description
+
+Shows debugging information about open MyISAM handles.
+my_end() exists primarily for MyISAM debugging.
+It would not normally be used in a production environment.
+It can give a nice summary of how you have used my_xxx() functions.
+It can be used to check that you have closed all files that you have opened.
+
+infoflag is the list function and can be:
+MY_CHECK_ERROR List which MyISAM handles are open.
+MY_GIVE_INFO Show runtime information.
+
+#.#.2 Return values
+
+Void
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+my_end(MY_CHECK_ERROR | MY_GIVE_INFO);
+====================
+#.# my_init()
+
+void my_init( void )
+
+#.#.1 Description
+
+Performs MyISAM initialisation for program startup, particularly if using threads.
+
+If using threads, be sure to call my_init() at start of program. (CFS does this in XPOPEN.) It is also safe to call my_init() when not using threads.
+
+#.#.2 Return values
+
+void
+Sometimes my_errno might be meaningful if a warning is generated during debugging.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+my_init();
+====================
+#.# init_key_cache()
+
+int init_key_cache( long int use_mem, (uint) reserve_mem;
+
+#.#.1 Description
+
+Starts and controls caching of keys. Call init_key_cache() to reserve memory for key caching and to start the caching. (CFS does this in XPOPEN if MYCACHE is defined (regular size), or MYCACHELARGE or MYCACHESMALL.)
+
+Provide use_mem the number of bytes of memory to use for key caching by this process.
+reserve_mem should be 0. This is just for very old systems with very little memory.
+
+#.#.2 Return values
+
+The number of 1kb memory blocks now allocated to key caching. Zero if key caching cannot be started (check my_errno), or key caching was already active.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+Blocks = init_key_cache( 65536L, IO_SIZE*4*10 );
+====================
+#.# _mi_make_key()
+
+uint _mi_make_key( MI_INFO *mip, uint keynr, uchar *key, const char *record, my_off_t filepos)
+
+#.#.1 Description
+
+Construct a key string for the given index, from the provided record buffer.
+??? When packed records are used ...
+This is an internal function, not for use by applications. Monty says: "This can't be used to create an external key for an application from your record."
+See mi_make_application_key() for a similar function that is useable by applications.
+
+The parameters are:
+A MI_INFO pointer mip.
+The index number keynr.
+The buffer to contain the formatted key string key.
+The record buffer record.
+??? A file position filepos or zero.
+
+#.#.2 Return values
+
+The byte length of the created key string.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+uint new_length=_mi_make_key(info,i,new_key,newrec,pos);
+====================
+#.# _mi_print_key()
+
+void _mi_print_key(FILE *stream, MI_KEYSEG *keyseg, const uchar *key, uint length)
+
+#.#.1 Description
+
+Prints a key in a user understandable format.
+This is an internal function for debugging, not for use by applications.
+??? Not yet fully documented. I just include it here so that I know it exists.
+
+#.#.2 Return values
+
+A readable print of the key contents goes to the specified output.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+
+_mi_print_key(stdout,share->keyinfo[info->errkey].seg,info->lastkey, USE_WHOLE_KEY);
+====================
+APPENDIX B Choosing a table type
+(excerpt from manual.txt in MySQL 3.23.8-alpha)
+
+With MySQL you can currently (version 3.23.5) choose between four usable table formats from a speed point of view.
+
+Static (Fixed-length) table characteristics
+* This is the default format. It's used when the table contains no `VARCHAR', `BLOB' or `TEXT' columns.
+* All `CHAR', `NUMERIC' and `DECIMAL' columns are space-padded to the column width.
+* Very quick.
+* Easy to cache.
+* Easy to reconstruct after a crash, because records are located in fixed positions.
+* Doesn't have to be reorganized (with `myisamchk') unless a huge number of records are deleted and you want to return free disk space to the operating system.
+* Usually requires more disk space than dynamic tables.
+
+Dynamic table characteristics
+* This format is used if the table contains any `VARCHAR', `BLOB' or `TEXT' columns.
+* All string columns are dynamic (except those with a length less than 4).
+* Each record is preceded by a bitmap indicating which columns are empty (`''') for string columns, or zero for numeric columns (this isn't the same as columns containing `NULL' values). If a string column has a length of zero after removal of trailing spaces, or a numeric column has a value of zero, it is marked in the bit map and not saved to disk. Non-empty strings are saved as a length byte plus the string contents.
+* Usually takes much less disk space than fixed-length tables.
+* Each record uses only as much space as is required. If a record becomes larger, it is split into as many pieces as required. This results in record fragmentation.
+* If you update a row with information that extends the row length, the row will be fragmented. In this case, you may have to run `myisamchk -r' from time to time to get better performance. Use `myisamchk -ei tbl_name' for some statistics.
+* Not as easy to reconstruct after a crash, because a record may be fragmented into many pieces and a link (fragment) 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 numeric columns
++ length of strings
++ (number of NULL columns + 7) / 8
+There is a penalty of 6 bytes for each link. A dynamic record is linked whenever an update causes an 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 `myisamchk -ed'. All links may be removed with `myisamchk -r'.
+
+Compressed table characteristics
+* A read-only table made with the `myisampack' utility. All customers with extended *MySQL* email support are entitled to a copy of `myisampack' for their internal usage.
+* The uncompress code exists in all *MySQL* distributions so that even customers who don't have `myisampack' can read tables that were compressed with `myisampack'
+* Takes very little disk space. Minimises disk usage.
+* Each record is compressed separately (very little access overhead). The header for a record is fixed (1-3 bytes) depending on the biggest record in the table. Each column is compressed differently. Some of the compression types are:
+- There is usually a different Huffman table for each column.
+- Suffix space compression.
+- Prefix space compression.
+- Numbers with value `0' are stored using 1 bit.
+- If values in an integer column have a small range, the column is stored using the smallest possible type. For example, a `BIGINT' column (8 bytes) may be stored as a `TINYINT' column (1 byte) if all values are in the range `0' to `255'.
+- If a column has only a small set of possible values, the column type is converted to `ENUM'.
+- A column may use a combination of the above compressions.
+* Can handle fixed or dynamic length records, but not `BLOB' or `TEXT' columns.
+* Can be uncompressed with `myisamchk'.
+
+*MySQL* can support different index types, but the normal type is ISAM.
+This is a B-tree index and you can roughly calculate the size for the index file as `(key_length+4)*0.67', summed over all keys. (This is for the worst case when all keys are inserted in sorted order.)
+
+String indexes are space compressed. If the first index part is a string, it will also be prefix compressed.
+Space compression makes the index file smaller if the string column has a lot of trailing space or is a `VARCHAR' column that is not always used to the full length.
+Prefix compression helps if there are many strings with an identical prefix.
+
+In memory table characteristics
+HEAP tables only exists in memory so they are lost if `mysqld' is taken down or crashes. But since they are *very* fast they are usefull as anyway.
+
+The *MySQL* internal HEAP tables uses 100% dynamic hashing without overflow areas and don't have problems with delete.
+
+You can only access things by equality using a index (usually by the `=' operator) whith a heap table.
+The downside with HEAPS are:
+ 1. You need enough extra memory for all HEAP tables that you want to use at the same time.
+ 2. You can't search on a part of a index.
+ 3. You can't search for the next entry in order (that is to use the index to do a `ORDER BY').
+1. *MySQL* also cannot find out how approximately many rows there are between two values. This is used by the optimizer to chose which index to use. But on the other hand no disk seeks are even needed.
+====================
+#.# mi_()
+
+#.#.1 Description
+
+#.#.2 Return values
+
+Zero if successful. Non-zero if an error occurred.
+
+#.#.3 Errors
+
+Nothing specific yet identified.
+
+#.#.4 Examples
+[SB1]int _mi_read_rnd_static_record(MI_INFO *info, byte *buf, my_off_t filepos,
+ my_bool skipp_deleted_blocks)
+int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf)
+
+Printed on 17/03/00
+
+C-7
diff --git a/Docs/mysqld_error.txt b/Docs/mysqld_error.txt
new file mode 100644
index 00000000000..b8f0ba72ba5
--- /dev/null
+++ b/Docs/mysqld_error.txt
@@ -0,0 +1,355 @@
+/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB
+ This file is public domain and comes with NO WARRANTY of any kind */
+
+#define ER_HASHCHK 1000
+"hashchk",
+#define ER_NISAMCHK 1001
+"isamchk",
+#define ER_NO 1002
+"NO",
+#define ER_YES 1003
+"YES",
+#define ER_CANT_CREATE_FILE 1004
+"Can't create file '%-.64s' (errno: %d)",
+#define ER_CANT_CREATE_TABLE 1005
+"Can't create table '%-.64s' (errno: %d)",
+#define ER_CANT_CREATE_DB 1006
+"Can't create database '%-.64s'. (errno: %d)",
+#define ER_DB_CREATE_EXISTS 1007
+"Can't create database '%-.64s'. Database exists",
+#define ER_DB_DROP_EXISTS 1008
+"Can't drop database '%-.64s'. Database doesn't exist",
+#define ER_DB_DROP_DELETE 1009
+"Error dropping database (can't delete '%-.64s', errno: %d)",
+#define ER_DB_DROP_RMDIR 1010
+"Error dropping database (can't rmdir '%-.64s', errno: %d)",
+#define ER_CANT_DELETE_FILE 1011
+"Error on delete of '%-.64s' (errno: %d)",
+#define ER_CANT_FIND_SYSTEM_REC 1012
+"Can't read record in system table",
+#define ER_CANT_GET_STAT 1013
+"Can't get status of '%-.64s' (errno: %d)",
+#define ER_CANT_GET_WD 1014
+"Can't get working directory (errno: %d)",
+#define ER_CANT_LOCK 1015
+"Can't lock file (errno: %d)",
+#define ER_CANT_OPEN_FILE 1016
+"Can't open file: '%-.64s'. (errno: %d)",
+#define ER_FILE_NOT_FOUND 1017
+"Can't find file: '%-.64s' (errno: %d)",
+#define ER_CANT_READ_DIR 1018
+"Can't read dir of '%-.64s' (errno: %d)",
+#define ER_CANT_SET_WD 1019
+"Can't change dir to '%-.64s' (errno: %d)",
+#define ER_CHECKREAD 1020
+"Record has changed since last read in table '%-.64s'",
+#define ER_DISK_FULL 1021
+"Disk full (%s). Waiting for someone to free some space....",
+#define ER_DUP_KEY 1022
+"Can't write, duplicate key in table '%-.64s'",
+#define ER_ERROR_ON_CLOSE 1023
+"Error on close of '%-.64s' (errno: %d)",
+#define ER_ERROR_ON_READ 1024
+"Error reading file '%-.64s' (errno: %d)",
+#define ER_ERROR_ON_RENAME 1025
+"Error on rename of '%-.64s' to '%-.64s' (errno: %d)",
+#define ER_ERROR_ON_WRITE 1026
+"Error writing file '%-.64s' (errno: %d)",
+#define ER_FILE_USED 1027
+"'%-.64s' is locked against change",
+#define ER_FILSORT_ABORT 1028
+"Sort aborted",
+#define ER_FORM_NOT_FOUND 1029
+"View '%-.64s' doesn't exist for '%-.64s'",
+#define ER_GET_ERRNO 1030
+"Got error %d from table handler",
+#define ER_ILLEGAL_HA 1031
+"Table handler for '%-.64s' doesn't have this option",
+#define ER_KEY_NOT_FOUND 1032
+"Can't find record in '%-.64s'",
+#define ER_NOT_FORM_FILE 1033
+"Incorrect information in file: '%-.64s'",
+#define ER_NOT_KEYFILE 1034
+"Incorrect key file for table: '%-.64s'. Try to repair it",
+#define ER_OLD_KEYFILE 1035
+"Old key file for table '%-.64s'; Repair it!",
+#define ER_OPEN_AS_READONLY 1036
+"Table '%-.64s' is read only",
+#define ER_OUTOFMEMORY 1037
+"Out of memory. Restart daemon and try again (needed %d bytes)",
+#define ER_OUT_OF_SORTMEMORY 1038
+"Out of sort memory. Increase daemon sort buffer size",
+#define ER_UNEXPECTED_EOF 1039
+"Unexpected eof found when reading file '%-.64s' (errno: %d)",
+#define ER_CON_COUNT_ERROR 1040
+"Too many connections",
+#define ER_OUT_OF_RESOURCES 1041
+"Out of memory; Check if mysqld or some other process uses all available memory. If not you may have to use 'ulimit' to allow mysqld to use more memory or you can add more swap space",
+#define ER_BAD_HOST_ERROR 1042
+"Can't get hostname for your address",
+#define ER_HANDSHAKE_ERROR 1043
+"Bad handshake",
+#define ER_DBACCESS_DENIED_ERROR 1044
+"Access denied for user: '%-.32s@%-.64s' to database '%-.64s'",
+#define ER_ACCESS_DENIED_ERROR 1045
+"Access denied for user: '%-.32s@%-.64s' (Using password: %s)",
+#define ER_NO_DB_ERROR 1046
+"No Database Selected",
+#define ER_UNKNOWN_COM_ERROR 1047
+"Unknown command",
+#define ER_BAD_NULL_ERROR 1048
+"Column '%-.64s' cannot be null",
+#define ER_BAD_DB_ERROR 1049
+"Unknown database '%-.64s'",
+#define ER_TABLE_EXISTS_ERROR 1050
+"Table '%-.64s' already exists",
+#define ER_BAD_TABLE_ERROR 1051
+"Unknown table '%-.64s'",
+#define ER_NON_UNIQ_ERROR 1052
+"Column: '%-.64s' in %-.64s is ambiguous",
+#define ER_SERVER_SHUTDOWN 1053
+"Server shutdown in progress",
+#define ER_BAD_FIELD_ERROR 1054
+"Unknown column '%-.64s' in '%-.64s'",
+#define ER_WRONG_FIELD_WITH_GROUP 1055
+"'%-.64s' isn't in GROUP BY",
+#define ER_WRONG_GROUP_FIELD 1056
+"Can't group on '%-.64s'",
+#define ER_WRONG_SUM_SELECT 1057
+"Statement has sum functions and columns in same statement",
+#define ER_WRONG_VALUE_COUNT 1058
+"Column count doesn't match value count",
+#define ER_TOO_LONG_IDENT 1059
+"Identifier name '%-.100s' is too long",
+#define ER_DUP_FIELDNAME 1060
+"Duplicate column name '%-.64s'",
+#define ER_DUP_KEYNAME 1061
+"Duplicate key name '%-.64s'",
+#define ER_DUP_ENTRY 1062
+"Duplicate entry '%-.64s' for key %d",
+#define ER_WRONG_FIELD_SPEC 1063
+"Incorrect column specifier for column '%-.64s'",
+#define ER_PARSE_ERROR 1064
+"%s near '%-.80s' at line %d",
+#define ER_EMPTY_QUERY 1065
+"Query was empty",
+#define ER_NONUNIQ_TABLE 1066
+"Not unique table/alias: '%-.64s'",
+#define ER_INVALID_DEFAULT 1067
+"Invalid default value for '%-.64s'",
+#define ER_MULTIPLE_PRI_KEY 1068
+"Multiple primary key defined",
+#define ER_TOO_MANY_KEYS 1069
+"Too many keys specified. Max %d keys allowed",
+#define ER_TOO_MANY_KEY_PARTS 1070
+"Too many key parts specified. Max %d parts allowed",
+#define ER_TOO_LONG_KEY 1071
+"Specified key was too long. Max key length is %d",
+#define ER_KEY_COLUMN_DOES_NOT_EXITS 1072
+"Key column '%-.64s' doesn't exist in table",
+#define ER_BLOB_USED_AS_KEY 1073
+"BLOB column '%-.64s' can't be used in key specification with the used table type",
+#define ER_TOO_BIG_FIELDLENGTH 1074
+"Too big column length for column '%-.64s' (max = %d). Use BLOB instead",
+#define ER_WRONG_AUTO_KEY 1075
+"Incorrect table definition; There can only be one auto column and it must be defined as a key",
+#define ER_READY 1076
+"%s: ready for connections\n",
+#define ER_NORMAL_SHUTDOWN 1077
+"%s: Normal shutdown\n",
+#define ER_GOT_SIGNAL 1078
+"%s: Got signal %d. Aborting!\n",
+#define ER_SHUTDOWN_COMPLETE 1079
+"%s: Shutdown Complete\n",
+#define ER_FORCING_CLOSE 1080
+"%s: Forcing close of thread %ld user: '%-.32s'\n",
+#define ER_IPSOCK_ERROR 1081
+"Can't create IP socket",
+#define ER_NO_SUCH_INDEX 1082
+"Table '%-.64s' has no index like the one used in CREATE INDEX. Recreate the table",
+#define ER_WRONG_FIELD_TERMINATORS 1083
+"Field separator argument is not what is expected. Check the manual","
+#define ER_BLOBS_AND_NO_TERMINATED 1084
+"You can't use fixed rowlength with BLOBs. Please use 'fields terminated by'.",
+#define ER_TEXTFILE_NOT_READABLE 1085
+"The file '%-.64s' must be in the database directory or be readable by all",
+#define ER_FILE_EXISTS_ERROR 1086
+"File '%-.80s' already exists",
+#define ER_LOAD_INFO 1087
+"Records: %ld Deleted: %ld Skipped: %ld Warnings: %ld",
+#define ER_ALTER_INFO 1088
+"Records: %ld Duplicates: %ld",
+#define ER_WRONG_SUB_KEY 1089
+"Incorrect sub part key. The used key part isn't a string or the used length is longer than the key part",
+#define ER_CANT_REMOVE_ALL_FIELDS 1090
+"You can't delete all columns with ALTER TABLE. Use DROP TABLE instead",
+#define ER_CANT_DROP_FIELD_OR_KEY 1091
+"Can't DROP '%-.64s'. Check that column/key exists",
+#define ER_INSERT_INFO 1092
+"Records: %ld Duplicates: %ld Warnings: %ld",
+#define ER_INSERT_TABLE_USED 1093
+"INSERT TABLE '%-.64s' isn't allowed in FROM table list",
+#define ER_NO_SUCH_THREAD 1094
+"Unknown thread id: %lu",
+#define ER_KILL_DENIED_ERROR 1095
+"You are not owner of thread %lu",
+#define ER_NO_TABLES_USED 1096
+"No tables used",
+#define ER_TOO_BIG_SET 1097
+"Too many strings for column %-.64s and SET",
+#define ER_NO_UNIQUE_LOGFILE 1098
+"Can't generate a unique log-filename %-.64s.(1-999)\n",
+#define ER_TABLE_NOT_LOCKED_FOR_WRITE 1099
+"Table '%-.64s' was locked with a READ lock and can't be updated",
+#define ER_TABLE_NOT_LOCKED 1100
+"Table '%-.64s' was not locked with LOCK TABLES",
+#define ER_BLOB_CANT_HAVE_DEFAULT 1101
+"BLOB column '%-.64s' can't have a default value",
+#define ER_WRONG_DB_NAME 1102
+"Incorrect database name '%-.100s'",
+#define ER_WRONG_TABLE_NAME 1103
+"Incorrect table name '%-.100s'",
+#define ER_TOO_BIG_SELECT 1104
+"The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok",
+#define ER_UNKNOWN_ERROR 1105
+"Unknown error",
+#define ER_UNKNOWN_PROCEDURE 1106
+"Unknown procedure '%-.64s'",
+#define ER_WRONG_PARAMCOUNT_TO_PROCEDURE 1107
+"Incorrect parameter count to procedure '%-.64s'",
+#define ER_WRONG_PARAMETERS_TO_PROCEDURE 1108
+"Incorrect parameters to procedure '%-.64s'",
+#define ER_UNKNOWN_TABLE 1109
+"Unknown table '%-.64s' in %-.32s",
+#define ER_FIELD_SPECIFIED_TWICE 1110
+"Column '%-.64s' specified twice",
+#define ER_INVALID_GROUP_FUNC_USE 1111
+"Invalid use of group function",
+#define ER_UNSUPPORTED_EXTENSION 1112
+"Table '%-.64s' uses an extension that doesn't exist in this MySQL version",
+#define ER_TABLE_MUST_HAVE_COLUMNS 1113
+"A table must have at least 1 column",
+#define ER_RECORD_FILE_FULL 1114
+"The table '%-.64s' is full",
+#define ER_UNKNOWN_CHARACTER_SET 1115
+"Unknown character set: '%-.64s'",
+#define ER_TOO_MANY_TABLES 1116
+"Too many tables. MySQL can only use %d tables in a join",
+#define ER_TOO_MANY_FIELDS 1117
+"Too many columns",
+#define ER_TOO_BIG_ROWSIZE 1118
+"Too big row size. The maximum row size, not counting BLOBs, is %d. You have to change some fields to BLOBs",
+#define ER_STACK_OVERRUN 1119
+"Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thread_stack=#' to specify a bigger stack if needed",
+#define ER_WRONG_OUTER_JOIN 1120
+"Cross dependency found in OUTER JOIN. Examine your ON conditions",
+#define ER_NULL_COLUMN_IN_INDEX 1121
+"Column '%-.64s' is used with UNIQUE or INDEX but is not defined as NOT NULL",
+#define ER_CANT_FIND_UDF 1122
+"Can't load function '%-.64s'",
+#define ER_CANT_INITIALIZE_UDF 1123
+"Can't initialize function '%-.64s'; %-.80s",
+#define ER_UDF_NO_PATHS 1124
+"No paths allowed for shared library",
+#define ER_UDF_EXISTS 1125
+"Function '%-.64s' already exist",
+#define ER_CANT_OPEN_LIBRARY 1126
+"Can't open shared library '%-.64s' (errno: %d %-.64s)",
+#define ER_CANT_FIND_DL_ENTRY 1127
+"Can't find function '%-.64s' in library'",
+#define ER_FUNCTION_NOT_DEFINED 1128
+"Function '%-.64s' is not defined",
+#define ER_HOST_IS_BLOCKED 1129
+"Host '%-.64s' is blocked because of many connection errors. Unblock with 'mysqladmin flush-hosts'",
+#define ER_HOST_NOT_PRIVILEGED 1130
+"Host '%-.64s' is not allowed to connect to this MySQL server",
+#define ER_PASSWORD_ANONYMOUS_USER 1131
+"You are using MySQL as an anonymous users and anonymous users are not allowed to change passwords",
+#define ER_PASSWORD_NOT_ALLOWED 1132
+"You must have privileges to update tables in the mysql database to be able to change passwords for others",
+#define ER_PASSWORD_NO_MATCH 1133
+"Can't find any matching row in the user table",
+#define ER_UPDATE_INFO 1134
+"Rows matched: %ld Changed: %ld Warnings: %ld",
+#define ER_CANT_CREATE_THREAD 1135
+"Can't create a new thread (errno %d). If you are not out of available memory, you can consult the manual for a possible OS-dependent bug",
+#define ER_WRONG_VALUE_COUNT_ON_ROW 1136
+"Column count doesn't match value count at row %ld",
+#define ER_CANT_REOPEN_TABLE 1137
+"Can't reopen table: '%-.64s'",
+#define ER_INVALID_USE_OF_NULL 1138
+"Invalid use of NULL value",
+#define ER_REGEXP_ERROR 1139
+"Got error '%-.64s' from regexp",
+#define ER_MIX_OF_GROUP_FUNC_AND_FIELDS 1140
+"Mixing of GROUP columns (MIN(),MAX(),COUNT()...) with no GROUP columns is illegal if there is no GROUP BY clause",
+#define ER_NONEXISTING_GRANT 1141
+"There is no such grant defined for user '%-.32s' on host '%-.64s'",
+#define ER_TABLEACCESS_DENIED_ERROR 1142
+"%-.16s command denied to user: '%-.32s@%-.64s' for table '%-.64s'",
+#define ER_COLUMNACCESS_DENIED_ERROR 1143
+"%-.16s command denied to user: '%-.32s@%-.64s' for column '%-.64s' in table '%-.64s'",
+#define ER_ILLEGAL_GRANT_FOR_TABLE 1144
+"Illegal GRANT/REVOKE command. Please consult the manual which privileges can be used.",
+#define ER_GRANT_WRONG_HOST_OR_USER 1145
+"The host or user argument to GRANT is too long",
+#define ER_NO_SUCH_TABLE 1146
+"Table '%-.64s.%-.64s' doesn't exist",
+#define ER_NONEXISTING_TABLE_GRANT 1147
+"There is no such grant defined for user '%-.32s' on host '%-.64s' on table '%-.64s'",
+#define ER_NOT_ALLOWED_COMMAND 1148
+"The used command is not allowed with this MySQL version",
+#define ER_SYNTAX_ERROR 1149
+"You have an error in your SQL syntax",
+#define ER_DELAYED_CANT_CHANGE_LOCK 1150
+"Delayed insert thread couldn't get requested lock for table %-.64s",
+#define ER_TOO_MANY_DELAYED_THREADS 1151
+"Too many delayed threads in use",
+#define ER_ABORTING_CONNECTION 1152
+"Aborted connection %ld to db: '%-.64s' user: '%-.32s' (%-.64s)",
+#define ER_NET_PACKET_TOO_LARGE 1153
+"Got a packet bigger than 'max_allowed_packet'",
+#define ER_NET_READ_ERROR_FROM_PIPE 1154
+"Got a read error from the connection pipe",
+#define ER_NET_FCNTL_ERROR 1155
+"Got an error from fcntl()",
+#define ER_NET_PACKETS_OUT_OF_ORDER 1156
+"Got packets out of order",
+#define ER_NET_UNCOMPRESS_ERROR 1157
+"Couldn't uncompress communication packet",
+#define ER_NET_READ_ERROR 1158
+"Got an error reading communication packets",
+#define ER_NET_READ_INTERRUPTED 1159
+"Got timeout reading communication packets",
+#define ER_NET_ERROR_ON_WRITE 1160
+"Got an error writing communication packets",
+#define ER_NET_WRITE_INTERRUPTED 1161
+"Got timeout writing communication packets",
+#define ER_TOO_LONG_STRING 1162
+"Result string is longer than max_allowed_packet",
+#define ER_TABLE_CANT_HANDLE_BLOB 1163
+"The used table type doesn't support BLOB/TEXT columns",
+#define ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 1164
+"The used table type doesn't support AUTO_INCREMENT columns",
+#define ER_DELAYED_INSERT_TABLE_LOCKED 1165
+"INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES",
+#define ER_WRONG_COLUMN_NAME 1166
+"Incorrect column name '%-.100s'",
+#define ER_WRONG_KEY_COLUMN 1167
+"The used table handler can't index column '%-.64s'",
+#define ER_WRONG_MRG_TABLE 1168
+"All tables in the MERGE table are not identically defined",
+#define ER_DUP_UNIQUE 1169
+"Can't write, because of unique constraint, to table '%-.64s'",
+#define ER_BLOB_KEY_WITHOUT_LENGTH 1170
+"BLOB column '%-.64s' used in key specification without a key length",
+#define ER_PRIMARY_CANT_HAVE_NULL 1171
+"All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead",
+#define ER_TOO_MANY_ROWS 1172
+"Result consisted of more than one row",
+#define ER_REQUIRES_PRIMARY_KEY 1173
+"This table type requires a primary key",
+#define ER_NO_RAID_COMPILED 1174
+"This version of MySQL is not compiled with RAID support",
+#define ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE 1175
+"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
diff --git a/Docs/net_doc.txt b/Docs/net_doc.txt
new file mode 100644
index 00000000000..e79ed9b5711
--- /dev/null
+++ b/Docs/net_doc.txt
@@ -0,0 +1,944 @@
+ MySQL Client - Server Protocol Ducumentation
+
+
+Introduction
+------------
+
+
+This paper has an objective of a through description of the
+client - server protocol which is embodied in MySQL. Particularly,
+this paper aims to document and describe:
+
+- manner in which MySQL server detects client connection requests and
+ creates connection
+- manner in which MySQL client C API call connects to server - the
+ entire protocol of sending / receiving data by MySQL server and C API
+ code
+- manner in which queries are sent by client C API calls to server
+- manner in which query results are sent by server
+- manner in which query results are resolved by server
+- sending and receiving of error messages
+
+
+This paper does not have the goal or describing nor documenting other
+related MySQL issues, like usage of thread libraries, MySQL standard
+library set, MySQL strings library and other MySQL specific libraries,
+type definitions and utilities.
+
+Issues that are covered by this paper are contained in the following
+source code files:
+
+- client/net.c and sql/net_serv.c, the two being identical
+- client/libmysql.c (not entire file is covered)
+- include/mysql_com.h
+- include/mysql.h
+- sql/mysqld.cc (not entire file is covered)
+- sql/net_pkg.cc
+- sql/sql_base.cc (not entire file is covered)
+- sql/sql_select.cc (not entire file is covered)
+- sql/sql_parse.cc (not entire file is covered)
+
+Beside this introduction this paper presents basic definitions,
+constants, structures and global variables, all related functions in
+server and in C API. Textual description of the entire protocol
+functioning is described in the last chapter of this paper.
+
+
+Constants, structures and global variables
+------------------------------------------
+
+This chapter will describe all constants, structures and
+global variables relevant to client - server protocol.
+
+Constants
+
+They are important as they contain default values, the ones
+that are valied if options are not set in any other way. Beside that
+MySQL source code does not contain a single non-defined constant in
+it's code. This description of constants does not include
+configuration and conditional compilation #defines.
+
+NAME_LEN - field and table name length, current value 64
+HOSTNAME_LENGTH - length of the host name, current value 64
+USERNAME_LENGTH - user name length, current vluae 16
+MYSQL_PORT - default TCP/IP port number, current value 3306
+MYSQL_UNIX_ADDR - full path of the default Unix socket file, current value
+ "/tmp/mysql.sock"
+MYSQL_NAMEDPIPE - full path of the default NT pipe file, current value
+ "MySQL"
+MYSQL_SERVICENAME - name of the MySQL Service on NT, current value "MySql"
+NET_HEADER_SIZE - size of the network header, when no
+ compression is used, current value 4
+COMP_HEADER_SIZE - additional size of network header when
+ compression is used, current value 3
+
+What follows are set of constants, defined in source only, which
+define capabilities of the client built with that version of C
+API. Simply, when some new feature is added in client, that client
+feature is defined, so that server can detect what capabilities a
+client program has.
+
+CLIENT_LONG_PASSWORD - client supports new more secure passwords
+CLIENT_LONG_FLAG - client uses longer flags
+CLIENT_CONNECT_WITH_DB - client can specify db on connect
+CLIENT_COMPRESS - client can use compression protocol
+CLIENT_ODBC - ODBC client
+CLIENT_LOCAL_FILES - client can use LOAD DATA INFILE LOCAL
+CLIENT_IGNORE_SPACE - client can Ignore spaces before '('
+CLIENT_CHANGE_USER - client supports the mysql_change_user()
+
+What follows are other constants, pertaining to timeouts and sizes
+
+MYSQL_ERRMSG_SIZE - maximum size of error message string, current value 200
+NET_READ_TIMEOUT - read timeout, current value 30 sec.
+NET_WRITE_TIMEOUT - write timeout, current value 60 sec.
+NET_WAIT_TIMEOUT - wait for new query timeout, current value 8*60*60
+ sec. i.e. 8 hours
+packet_error - value returned in case of socket errors, current
+ value -1
+TES_BLOCKING - used in debug mode for setting up blocking testing
+RETRY COUNT - number of times network read and write will be
+ retried, current value 1
+
+There are also error messages for last_errno, which depict system
+errors, and are used on the server only.
+
+ER_NET_PACKAGE_TOO_LARGE - packet is larger then max_allowed_packet
+ER_OUT_OF_RESOURCES - practically no more memory
+ER_NET_ERROR_ON_WRITE - error in writing to NT Named Pipe
+ER_NET_WRITE_INTERRUPTED - some signal or interrupt happened
+ during write
+ER_NET_READ_ERROR_FROM_PIPE - error in reading from NT Named Pipe
+ER_NET_FCNTL_ERROR - error in trying to set fcntl on socket
+ descriptor
+ER_NET_PACKETS_OUT_OF_ORDER - packet numbers on client and
+ server side differ
+ER_NET_UNCOMPRESS_ERROR - error in uncompress of compressed packet
+
+
+ Structs and eunms
+
+
+struct NET
+
+this is MySQL's network handle structure, used in all client / server
+read/write functions. On the server it is initialized and preserved in
+each thread. On the client, it is a part of MYSQL struct, which is
+MySQL handle used in all C API functions. This structure uniquely
+identifies a connection, either on the server or client side.
+This structure consists of the following
+fields:
+
+ Vio* vio; - explained above
+ HANDLE hPipe - Handle for NT Named Pipe file
+ my_socket fd - file descriptor used for both tcp socket and Unix socket file
+ int fcntl - contains info on fcntl options used on fd. Mostly
+ used for saving info if blocking is used or not
+ unsigned char *buff - network buffer used for storing data for
+ reading from / writing to socket
+ unsigned char,*buff_end - points to the end of buff
+ unsigned char *write_pos - present writing position in buff
+ unsigned char *read_pos - present reading postiion in
+ buff. This pointer is used for
+ reading data after calling
+ my_net_read function and function
+ that are just it's wrappers
+ char last_error[MYSQL_ERRMSG_SIZE] - holds last error message
+ unsigned int last_errno - holds last error code of the network
+ protocol. It's ossible values are
+ listed in above constants. It is
+ used only on the server side
+ unsigned int max_packet - holds current value of buff size
+ unsigned int timeout - stores read timeout value for that connection
+ unsigned int pkt_nr - stores a value of the current packet
+ number in a batch of packets. Used
+ primarily for detection of protocol
+ errors resulting in a mismatch
+ my_bool error - holds either 1 or 0 depending on the error condition
+ my_bool return_errno - if it's value != 0 then there is an
+ error in protocol mismatch between
+ client and server
+ my_bool compress - if true compression is used in the protocol
+ unsigned long remain_in_buf - used only in reading compressed
+ packets. Explained in my_net_read
+ unsigned long length - used only for storing a length of the
+ read packet. Explained in my_net_read
+ unsigned long buf_length - used only in reading compressed
+ packets. Explained in my_net_read
+ unsigned long where_b - used only in reading compressed
+ packets. Explained in my_net_read
+ short int more - used for reporting in mysql_list_processes
+ char save_char - used in reading compressed packets for saving
+ chars in order to make zero-delimited
+ strings. Explained in my_net_read
+
+Few typedefs will be defined for easier understanding of the text that
+follows.
+
+ typedef char **MYSQL_ROW - data containing one row of values
+ typedef unsigned int MYSQL_FIELD_OFFSET - offset in bytes of
+ the current field
+ typedef MYSQL_ROWS *MYSQL_ROW_OFFSET - offset in bytes of
+ the current row
+
+
+ struct MYSQL_FIELD - contains all info on the attributes of a
+specific column in a result set, plus info on lengths of the column in
+a result set. This struct is tagged as st_mysql_field. This structure
+consists of the following fields:
+
+ char *name - name of column
+ char *table - table of column if column was a field and not
+ expression or constant
+ char *def - default value (set by mysql_list_fields)
+ enum enum_field_types type - see above
+ unsigned int length - width of column in a current row
+ unsigned int max_length - maximum width of that column in
+ entire result set
+ unsigned int flags - corresponding to Extra in DESCRIBE
+ unsigned int decimals - number of decimals in field
+
+
+ struct MYSQL_ROWS - a node for each row in the single linked
+list forming entire result set. This struct is tagged as
+st_mysql_rows, and has two fields:
+
+ struct st_mysql_rows *next - pointer to a next one
+ MYSQL_ROW data - see above
+
+
+ struct MYSQL_DATA - contains all rows from result set. It is
+tagged as st_mysql_data and has following fields:
+
+ my_ulonglong rows - how many rows
+ unsigned int fields - how many columns
+ MYSQL_ROWS *data - see above. This is a first node of the
+ linked list
+ MEM_ROOT alloc - MEM_ROOT is MySQL memory allocation
+ structure, and this field is used to store
+ all fields and rows.
+
+
+ struct st_mysql_options - holds various client options, and
+contains following fields:
+
+ unsigned int connect_timeout - time in sec. for cennection
+ unsigned int client_flag - used to cold client capabilities
+ my_bool compress - boolean for compression
+ my_bool named_pipe - is Named Pipe used on NT
+ unsigned int port - what TCP port is used
+ char *host - host to connect to
+ char *init_command - command to be executed upon connection
+ char *user - account name on MySQL server
+ char *password - password for the above
+ char *unix_socket - full path for Unix socket file
+ char *db - default database
+ char *my_cnf_file - optional configuration file
+ char *my_cnf_group - optional header for options
+
+
+ struct MYSQL - MySQL client's handle. Required for any
+operation issed from client to server. Tagged as st_mysql and having
+following fields:
+
+ NET net - see above
+ char *host - host on which MySQL server is running
+ char *user - MySQL user name
+ char *passwd - password for above
+ char *unix_socket- full path of Unix socket file
+ char *server_version - version of the server
+ char *host_info - contains info on how has connection been
+ established, TCP port, socket or Named Pipe
+ char *info - used to store information on the query results,
+ like number of rows affected etc.
+ char *db - current database
+ unsigned int port -= TCP port in use
+ unsigned int client_flag - client capabilities
+ unsigned int server_capabilities - server capabilities
+ unsigned int protocol_version - version of the protocl
+ unsigned int field_count - used for storing number of fields
+ immidiately upon execution of a
+ query, but before fetching rows
+ unsigned long thread_id - server thread to which this connection is attached
+ my_ulonglong affected_rows - used for storing number of rows
+ immidiately upon execution of a
+ query, but before fetching rows
+ my_ulonglong insert_id - fetching LAST_INSERT_ID() through
+ client C API
+ my_ulonglong extra_info - used by mysqlshow
+ unsigned long packet_length - saving size of the first packet
+ upon execution of a query
+ enum mysql_status status - see above
+ MYSQL_FIELD *fields - see above
+ MEM_ROOT field_alloc - memory used for storing previous field
+ (fields)
+ my_bool free_me - boolean that flags if MYSQL was allocated in
+ mysql_init
+ my_bool reconnect - used to automatically reconnect
+ struct st_mysql_options options - see above
+ char scramble_buff[9] - key for scrambling password before
+ sending it to server
+
+
+ struct MYSQL_RES - tagged as st_mysql_res and used to store
+entire result set from a single query. Contains following fields:
+
+ my_ulonglong row_count - number of rows
+ unsigned int field_count - number of columns
+ unsigned int current_field - cursor for fetching fields
+ MYSQL_FIELD *fields - see above
+ MYSQL_DATA *data - see above, and used in buffered reads,
+ i.e. mysql_store_result only
+ MYSQL_ROWS *data_cursor - pointing to the field of above "data"
+ MEM_ROOT field_alloc - memory allocation for above "fields"
+ MYSQL_ROW row - used for storing row by row in unbuffered
+ reads, i.e. in mysql_use_result
+ MYSQL_ROW current_row - cursor to the current row for buffered
+ reads
+ unsigned long *lengths - column lengths of current row
+ MYSQL *handle - see above, used in unbuffered reads, i.e. in
+ mysql_use_resultq
+ my_bool eof - used my mysql_fetch_row as a marker for end of data
+
+
+
+
+ Global variables
+
+
+ unsigned long max_allowed_packet - maximum allowable value of
+ network buffer. Default
+ value - 1 Mb
+
+ unsigned long net_buffer_length - default, starting value of
+ network buffer - 8 Kb
+
+ unsigned long bytes_sent - total number of bytes written since
+ startup of the server
+
+ unsigned long bytes_received - total number of bytes read
+ since startup of the server
+
+
+ Synopsis of the basic client - server protocol
+ ----------------------------------------------
+
+ Purpose of this chapter is to provide a complete picture of
+the basic client - server protocol implemented in MySQL. It was felt
+it is necessary after writting descriptions for all of the functions
+involved in basic protocol. There are at present 11 functions
+involved, with several structures, many constants etc, which are all
+described in detail. But as a forest could not be seen from the trees,
+so a concept of the protocol could not be deciphered easily from a
+thourough documentation on minutae.
+
+ Althouch concept of the protocol was not changed with the
+introduction of vio system, embodied in violate.cc source file and VIO
+system, the introduction of these has changed a code substantially. Before
+VIO was introduced, functions for reading from / writing to network
+connection had to deal with various network standards. So, these functions
+depended on whether TCP port or Unix socket file or NT Named Pipe file is
+used. This is all changed now and single vio_ functions are called, while
+all this diversity is covered by vio_ functions.
+
+ In MySQL a specific buffered network input / output transport
+model has been implemented. Although each operating system mah have
+it's own buffering for network connections, MySQL has added it's own
+buffering model. This same for each of the three transport protocol
+types that are used in MySQL client - server communications, which are
+tcp sockets (on all systems), Unix socket files on Unix and Unix-like
+operating systems and Named Pipe files on NT. Alghouth tcp sockets
+are omnipresent, the later two types have been added for local
+connections. Those two connection types can be used in local modes
+only, i.e. when both client and server reside on the same host, and
+are introduced because they enable better speeds for local
+connections. This is especially usefull for WWW type of
+applications. Startup options of MySQl server allow that either tcp
+sockets or local connection (OS dependent) can be disallowed.
+
+ In order to be able to implement buffered input / output MySQL
+allocates a buffer. A starting size of this buffer is determined by a
+value of the global variable net_buffer_length, which can be changed
+at MySQL server startup. This is, as explained only a startup length
+of MySQL network buffer. As a signle item that has to be read /
+written can be larger then that value, MySQL will increase buffer size
+as long as that size reaches value of global variable
+max_aallowed_packet, which is also settable at server startup. Maximum
+value of this variable is limited by the way MySQL stores / reads
+sizes of packets to be sent / read, which means by the way MySQL
+formats packages.
+
+ Basically each packet consists of two parts, a header and
+data. In the case when compression is not used, header consists of 4
+bytes of which 3 contain a length of the packet to be sent and one
+holds a packet number. When compression is used there are
+onother 3 bytes which store a size of uncompressed data. Because of
+the way MySQL packs length into 3 bytes, plus due to the usage of some
+special values in the most significant byte, maximum size of
+max_allowed_packet is limited to 24 Mb at present. So, if compression
+is not used, at first 4 bytes are written to the buffer and then data
+itself. As MySQL buffers I/O logical packets are packet together until
+packets fill up entire size of the buffer. That size no less then
+net_buffer_size, but no greater then max_allowed_packet. So, actuall
+writting to the network is done when this buffer is filled up. As
+frequently sequence of buffers make a logicall unit, like a result
+set, then at the end of sending data, even if buffer is not full, data
+is written, i.e. flushed to the connection with a call of the
+net_flush function. In order to maintain that no single packet can be
+larger then this value, checks are made throughout a code, so that not
+signle field or command could exceed that value.
+
+ In order to maintain coherency in consicutive packets, each
+packet is numbered and their number stored as a part of a header, as
+explained above. Packets start with 0, so whenever a logical packet is
+written, that number is incremented. On the other side when packets
+are read, value that is fetched is compared with a value stored and if
+there is no mismatch that value is incremented too. Packet number is
+reset on the client side when unwanted connections are removed from
+the connection and on the server side when a new command hsa been
+started.
+
+
+ So, before writting, a buffer contains a sequence of logical
+packets, consisting of header plus data consequtively. In the case
+that compression is used, packet numbers are not stored in each header
+of the logical packets, but a whole buffer, or a part of it if
+flushing is done, containing one or more logical packets are
+compressed. In that case a new larger header, is formed, and all
+logical packets contained in the buffer are compressed together. This
+way only one packet is formed which makes several logical packets,
+which improves both speed and compression ratio. On the other side,
+when this large compressed packet is read, it is furst uncompressed,
+and then logical packets are sent, one by one, to the calling
+functions.
+
+
+ All this functionality is described in detail in the following
+chapter. It does not contain functions that form logical packets, or
+that read and write to connections but also functions that are used
+for initialisation, clearing of connections. There are functions at
+higher level dealing with sending fields, rows, establishing
+connections, sending commands, but those are not explained in the
+following chapter.
+
+
+ Functions utilized in client - server protocol
+ ----------------------------------------------
+
+ First of all, functions are described that are involved in
+praparing/ reading / writing data over TCP port , socket or named pipe
+file, and functions directly related to those. All of these functions
+are used both in server and client. Server and client specific code
+segments will be documented in each function description. Each MySQl
+function checks for errors in memory allocation / freeing, as well as
+in every OS call, like the one dealing with files and sockets, and for
+errors in indeginous MySQL function calls. This is expected, but has
+to be said, as not to repeat it in every function description.
+
+ Older versions of MySQL have utilized the following macros for
+reading from / writing to socket.
+
+ raw_net_read - calls OS function recv function that reads N
+ bytes from a socket into a buffer. Number of
+ bytes read is returned.
+
+ raw_net_write - calls OS funciton send to write N bytes from
+ a buffer to socket. Number of bytes written
+ is returned.
+
+ These macros are replaced with VIO (Virtual I/O) functions.
+
+
+ Function name: my_net_init
+
+ Parameters: struct NET *, enum_net_type, struct Vio
+
+ Return value : 1 for error, 0 for success
+
+ Function purpose: To initialize properly all NET fields,
+ allocate memory and set socket options
+
+ Function description
+
+ First of all, buff field of NET struct is allocated to the
+size of net_buffer_lenght, and on failure function exits with 0. All
+fields in NET are set to their default or starting values. As
+net_buffer_length and max_allowed_packet are configurable,
+max_allowed_packet is set equal to net_buffer_length it the later one
+is greater. max_packet if set for that NET to net_buffer_lenght, and
+buff_end points to buff end. vio feild is set to the second parameter.
+If it is a real connection, which is a case when second parameter is
+not null, then fd field is set by calling vio_fd function.read_pos and
+write_pos to buff, while remaining integers are set to 0. If function
+is run on the MySQL server on Unix and server is started in a test
+mode that would require testing of blocking, then vio_blocking
+function is called. Last, fast throughput mode is set by a call to
+vio_fastsend function.
+
+
+
+ Function name: net_end
+
+ Parameters: struct NET *
+
+ Return value : void
+
+ Function purpose: To release memory alloceted to buff
+
+
+
+ Function name: net_realloc (private, static function)
+
+ Parameters: struct NET, unlong (unsigned long)
+
+ Return value : 1 for error, 0 for success
+
+ Function purpose: To change memory allocated to buff
+
+ Function description
+
+ New length of buff field of NET struct is passed as second
+parameter. It is first checked versus max_allowd_packet and if greater
+error is returned. New length is aligned to 4096 boundary. Then , buff
+is reallocated, buff_end, max_packet and write_pas reset to the same
+values as in my_net_init.
+
+
+
+ Function name: net_clear (used on client side only)
+
+ Parameters: struct NET *
+
+ Return value : void
+
+ Function purpose: To read unread packets
+
+ Function description
+
+ This function is used on client side only, and is executed
+only if a program is not started in test mode. This function reads
+unread packets without processing them. First, non-blocking mode is
+set on systems that have not non-blocking mode defined. This is
+performed by checking a mode with vio_is_blocking function. and
+setting non-blocking mode by vio_blocking function. If this operation
+was successfull, then packets are read by vio_read function, to which
+vio field of NET is passed together with buff and max_packet field
+values. field of the same struct at a length of max_packet. If
+blocking was active before reading is performed, blocking is set with
+vio_blocking function. AFter reading has been performed, pkt_nr is
+reset to 0 and write_pos reset to buff. In order to clarify some
+matters non-blocking mode enables executing program to dissociate from
+a connection, so that error in connection would not hang entire
+program or it's thread.
+
+ Function name: net_flush
+
+ Parameters: struct NET *
+
+ Return value : 1 for error, 0 for success
+
+ Function purpose: To write remaining bytes in buff to socket
+
+ Function description
+
+ net_real_write (described below) is performed is write_pos
+differs from buff, both being fields of the only parameter. write_pos
+is reset to buff. This function has to be used, as MySQL uses buffered
+writes, as it will be more explained in a function net_write_buff.
+
+
+ Function name: my_net_write
+
+ Parameters: struct NET *, const char *, ulong
+
+ Return value : 1 for error, 0 for success
+
+ Function purpose: Write a logical packet in a first parameter
+ of second parameter length
+
+ Function description
+
+ The purpose of this function is to prepare a logical packet
+such that entire content of data, pointed to by second parametar and
+in length of third parameter is sent to the other side. In case of
+server, it is used for sending result sets, and in case of client it
+is used for sending local data. This function foremost prepares a
+header for the packet. Normal, header consists of 4 bytes, of which
+first 3 bytes contain a length of the packet, thereby limiting a
+maximum allowable length of a packet to 16 Mb, while a fourth byte
+contains a packet number, which is used when one large packet has to
+be divided into sequence of packets. This way each sub-packet gets
+it's number which should be matched on the other side. When
+compression is used another three bytes are added to packet header,
+thus packet header is in that case increased to 7 bytes. Additional
+three bytes are used to save a length of compressed data. As in
+connection that uses compression option, code packs packets together,,
+a header prepared by this function is later not used in writting to /
+reading from network, but only to distinguish logical packets within a
+buffered read operation.
+
+
+ This function, first stores a value for third parameter into a
+first 3 bytes of local char variable of NET_HEADER_SIZE size by usage
+of function int3store. Then, at this point, if compression is not
+used, pkt_nr is increased, and it's value stored in the last byte of
+the said local char[] variable. If compression is used 0 is stored in
+both values. Then those four bytes are sent to other side by the usage
+of the function net_write_buff(to be explained later on), and
+successfull, entire packet in second parameter of the length described
+in third parameter is sent by the usage of the same function.
+
+
+ Function name: net_write_command
+
+ Parameters: struct NET *, char, const char *, ulong
+
+ Return value : 1 for error, 0 for success
+
+ Function purpose: Send a command with a packet as in previous
+ function
+
+ Function description
+
+ This function is very similar to the previous one. The only
+difference is that first packet is enlarged by one byte, so that a
+command precedes a packet to be sent. This is implemented by
+increasing fist packet by one byte, which contains a command code. As
+command codes do not use a range of values that are used by chararcter
+sets, so when the other side receives a packet, first byte after
+header contains a command code. This function is used by client for
+sending all commands and queries, and by server in connection process
+and for sending errors.
+
+
+ Function name: net_write_buff (private, static function)
+
+ Parameters: struct NET *, const char *, uint
+
+ Return value : 1 for error, 0 for success
+
+ Function purpose: To write a packet of vany size by cutting it
+ and using next function for writing it
+
+ Function description
+
+ This function was created after compression feature has been
+added to MySQL. This function supposes that packets have already been
+properly formatted, regarding packet header etc. Principal reason for
+this function existst because a packet that is sent by client or
+server does not have to be less then max_packet. So this function
+first calculeates how much data has been left in a buff, by getting a
+difference between buff_end and write_pos and storing it to local
+variable left_length. Then a loop is run as long as a length to be
+sent is greater then length of left bytes (left_length). In a loop
+data from second parameter is copied to buff at write_pos, as much as
+it can be, i.e. by left_length. Then net_real_write function is called
+(see below) with NET, buff, and max_packet parameters. This function
+is the lowest level fucntion that writes data over established
+connection. In a loop, write_pos is reset to buff, a pointer to data
+(second parameter) is moved by teh amount of data sent (left_length),
+length of data to be sent (third parameter) is decreased by the amount
+sent (left_length) and left_length is reset to max_packet value, which
+ends a loop. This logic was necessary, as there could have been some
+data yet unsent (write_pos != buf), while data to be sent could be as
+large as necessary, thus requiring many loops. At the end of function,
+remaining data in second parameter are copied to buff at write_pos, by
+the remaining length of data to be sent (third parameter). So, in the
+next call of this function remaining data will be sent, as buff is
+used in a call to net_real_write. It is very important to note that if
+a packet to be sent is less then a number of bytes that are still
+available in buff, then there will be no writing over network, but
+only logical packets will be added one after another. This will
+accelerate network traffic, plus if a compression is used, the
+expected compression rate would be higher. That is why server or
+client functions that sends data uses at the end of data net_flush
+function described above.
+
+
+ Function name: net_real_write
+
+ Parameters: struct NET *, const char *, ulong
+
+ Return value : 1 for error, 0 for success
+
+ Function purpose: To write data to a socket or pipe, with
+ compression if used
+
+ Function description
+
+ First, more field is set to 2, to enable reporting in
+mysql_list_processes. Then if compression is enabled on that
+connection, a new local buffer (variable b) is initialized to the
+length of total header (normal header + compression header) and if no
+memory is available error is returned. This buffer (b) is used for
+holding a fineal, compressed packet to be written ove
+connection. Furthermore in compressiion initialization, Second
+parameter at length of third parameter is copied to the local buffer
+b, and MySQL's wrapped zlib's compression function is run at total
+header offset of the local buffer. Please, do note that this function
+does not test effectiveness of compression. If compression is turned
+on in some connection, it is used all of the time. Also, it is very
+important to be cognizant of the fact that this algorithm makes
+possible that a single compressed packet contains several logical
+packets. In this way compression rate is increased and network
+throughput is increased as well. However, this algorithm has
+consequences on the other sided, that reads compressed packet, which
+is covered in my_net_read function. After compression is done, a full
+compression header is properly formed with a packet number,
+compressed and uncompressed lengths. At the end of compression code,
+third parameter is increased by total header length, as the original
+header is not used (see above), and second parameter, pointer to data,
+is set to point to local buffer b, in order that a further flow of
+function is independent of compression. . If a function is executed
+on server side, a thread alarm initialized and if non-blocking is
+active set at NET_WRITE_TIMEOUT. Two local (char *) pointers are
+initialized, pos at beginning of second parameter, and end at end of
+data. Then a loop is run as long as all data is written, which means
+as long as pos != end. First vio_write function is called, with
+parameters of vio field, pos and size of data (end - pos). Number of
+bytes written over connection is saved in local variable (length). If
+error is returned local bool variable (interrupted) is set according
+to the return value of the vio_should_retry called with vio field as
+parameter. This bool variable indicates whether writing was
+interrupted in some way or not. Firther, error from vio_write is
+differently treated on Unix versus other OS's (Win32 or OS/2). On Unix
+an alarm is set if one is not in use, no bytes have been written and
+there has been no interruption. Also, in that case, if connection is
+not in blocking mode, a sub - loop is run as long as blocking is not
+set with vio_blocking function. Withing a loop another run of above
+vio_write is run based on return value of vio_is_retry function,
+-provided number of repeated writes is less then RETRY_COUNT. If that
+is not a case, error field of struct NET. is set to 1 and function
+exits. At the exit of sub-llop number of reruns already executed is
+reset to zero and another run of above vio_write function is
+attempted. If a function is run on Win32 and OS/2, and in the case
+that function flow was not interrupted and thread alarm is not in use,
+again a main loop is continued until pos != end. In the case that this
+function is executed on thread safe client program, a communication
+flow is tested on EINTR, caused by context switching, by use of
+vio_errno function, in which case a loop is continued. At the end of
+processing of the error from vio_write, error field of struct NET is
+set, and if on server last_errno field is set to
+ER_NET_WRITE_INTERRUPTED in the case thatb local bool variable
+(interrupted) is true or to ER_NET_ERROR_ON_WRITE. Before the end of
+loop, in order to make possible evaluation of the loop condition, pos
+is increased by a value writen in last iteration (length). Also global
+variable bytes_sent is increased by the same value, for status
+purposes. At the end of the functions more fields is reset, in case
+of compression, combression buffer (b) memory is released and if
+thread is still in use, it is ended and blocking state is reset to
+it's original state, and function returns error is all bytes are not
+written.
+
+
+
+ Function name: my_real_read (private, static function)
+
+ Parameters: struct NET *, ulong *
+
+ Return value : length of bytes read
+
+ Function purpose: low level network connection read function
+
+ Function description
+
+ This function has made as a separate one when compression was
+introduced in MySQL client - server protocol . It contains basic, low
+level network reading functionality, while all dealings with
+compressed packets are handled in next function. Compression in this
+function is only handled in as much to unfold a length of uncompressed
+data. First blocking state of connection is saved in local bool
+variable net_blocking, and field more is set 1 for deteiled reporting
+in mysqld_list_processes. A new thread alarm is initialized, in order
+to enable read timout handling, and if on server and a connection can
+block a program, the alarm is set at a value of timeout field. Local
+pointer is set to the position of the next logical packet, with it's
+header skipped, which is at field where_b offset from buff. Next, a
+two time run code is entered. A loop is run exactly two times becase
+first time number of bytes to be fetched (remain) are set to the
+header size, which is different when compression is used or not used
+on the connection. After first fetch has been done, number of packets
+that will be received in second iteration is well known, as fetched
+header contains a size of packet, packet number ,and in a case of
+compression a size of uncompressed packet. Then as long, as there are
+bytes to read a loop is entered with ffirst reading data from network
+connection with vio_read function, called with parameters of field
+vio, current position and remaining number of bytes, which value is
+hold by local variable (remain) initialized at a value of header size,
+which differs if compression is used. Number of bytes read are
+returned in local length variable. If error is returned local bool
+variable (interrupted) is set according to the return value of the
+vio_should_retry called with vio field as parameter. This bool
+variable indicates whether reading was interrupted in some way or not.
+Firther, error from vio_read is differently treated on Unix versus
+other OS's (Win32 or OS/2). On Unix an alarm is set if one is not in
+use, no bytes have been read and there has been no interruption. Also,
+in that case, if connection is not in blocking mode, a sub - loop is
+run as long as blocking is not set with vio_blocking function. Withing
+a loop another run of above vio_read is run based on return value of
+vio_is_retry function, -provided number of repeated writes is less
+then RETRY_COUNT. If that is not a case, error field of struct NET. is
+set to 1 and function exits. At the exit of sub-llop number of reruns
+already executed is reset to zero and another run of above vio_read
+function is attempted. If a function is run on Win32 and OS/2, and in
+the case that function flow was not interrupted and thread alarm is
+not in use, again a main loop is continued as long as there are bytes
+remaining. In the case that this function is executed on thread safe
+client program, then if a another run should be made, which is decided
+by the output of vio_should_retry function, in which case a loop is
+continued. At the end of processing of the error from vio_read, error
+field of struct NET is set, and if on server last_errno field is set
+to ER_NET_READ_INTERRUPTED in the case thatb local bool variable
+(interrupted) is true or to ER_NET_ERROR_ON_READ. In case of such an
+error this function exits and returns error. In a case when there is
+no error, number of remaining bytes (remain) is decreased by a number
+of bytes read, which should be zero, but in case it is not the entire
+code is still in while (remain > 0) loop, which will be exited
+immediately if it is. This has been done to accomodate errors in the
+traffic level and for the very slow connections. Current position in
+field buff is also moved by the amount of bytes read by vio_read
+funciton, and global variable bytes_received is increased by the same
+value in a thread safe manner. When a loop that is run until necessary
+bytes are read (remain) is finished, then if external loop is in it's
+first run, of the two, packet sequencing is tested on consistency by
+comparing a number contained at 4th byte in header with pkt_nre
+field. Header location is found at where_b offset to field_b. Usage of
+where_b is obligatory due to the possible compression usage. If there
+is no compression on a connection, then where_b is always 0. If there
+is a discrepancy, then first byte of the header is checked whether it
+is equal to 255, because when error is sent by a server, or by a
+client if it is sending data (like in LOAD DATA INFILE LOCAL...), then
+first byte in header is set to 255. If it is not 255, then an error on
+packets being out of order is printed. In any case, on server,
+last_errno field is set to ER_NET_PACKETS_OUT_OF_ORDER and a function
+returns with the error, i.e. value returned is packet_error. If a
+check on serial number of packet is successful, pkt_nr field is
+incremented in order to enable checking packet order with next packet
+and if compression is used, uncompressed length is extracted from a
+proper position in header and returned in the second parameter of this
+function. Length of the packet is saved, for the purpose of a proper
+return value from this function. Still in the first iteration of the
+main loop, a check must be made if field buff could accomodate entire
+package that comes, in it's compressed or uncompressed form. This is
+done in such a way, because zlib's compress and uncompress functions
+use a same memory area for compression / uncompression. Necessary
+field buff length is equal to current offset where data are (where_b
+which is zero for non-compression), plus the larger value of
+compressed or uncompressed package to be read in a second run. If this
+value is larger then a current length of field buff, which is read
+from field max_packet, then feild buff has to be reallocated. IF
+reallocation with net_realloc function fails, function is returned
+with error. Before a second loop is started, length to be read is set
+to the length of expected data and current position (pos) is set at
+where_b offset from field buff. At the end of function, if alarm is
+set, which is a case if it is run on server or on a client if a
+function is interrupted and another run of vio_read is attempted,
+alarm is ended and blocking state is resotred from the saved local bool
+variable net_blocking. Function returns number of bytes read or the
+error (packet_error).
+
+
+
+
+ Function name: my_net_read
+
+ Parameters: struct NET *
+
+ Return value : length of bytes read
+
+ Function purpose: Highest level general purpose reading function
+
+ Function description
+
+ First, if compression is not used, my_real_read is called,
+with struct NET * a first parameter, and pointer to local ulong
+complen as a second parameter, but it's value is not used here.
+Number of bytes read is returned in local ulong variable len. read_pos
+field is set to an offset of value of where_b field from field
+buff. where_b field actually denotes where in field buff is a current
+packet. If returned number of bytes read (local variable len) does not
+signal that an error in packet trnasmission occured, i.e. it is not
+set to packet_error, then a string contained in read_pos is zero
+terminated. Simply, the end of a string starting at read_pos, and
+ending at read_pos + len, is set to zero. This is done in that way,
+because mysql_use_result expects a zero terminated string, and
+function returns with a value local variable len. This ends this
+function in the case that compression is not used and a remaining code
+is executed only if compression is enabled on the connection. In
+order to explain how is compressed packet logically cut into
+meningfull packets, a full meaning of several NET feilds should be
+explained. First of all, fields in NET are used and not local
+variables, as all values should be saved between consecutive calls of
+this function. Simply, this function is called in order to return
+logical packets, but this function does not need to call my_real_read
+function everytime, because when a large packet is uncompressed, it
+may, but not necessarily so, contain several logical
+packets. Therefore, in oreder to preserve data on logical packets
+local variables are not used. Instead fields in NET struct are
+used. Field remain_in_buf denotes how many bytes of entire
+uncompressed packets is still contained withing buff. field buf_length
+saves a value of the length of entire uncompressed packet. field
+save_char is used to save a character at a position where a packet
+ends, which character has to be replaced with a zero, '\0', in order
+to make a logical packet zero delimited, for mysql_use_result. Field
+length stores a value of the length of compressed packet. Field
+read_pos as usual, points to the current reading position. This char *
+pointer is used by all fucntion calling this function in order to
+fetch their data. Field buff is not used for that purpose, but
+read_pos is used instead. This change was introduced with compression,
+when algorihtm accomodated grouping of several packets together. Now,
+that meanings of all relevant NET fields is complained, we can proceed
+with a flow of this functinn in case when compression is
+active. First, if there are remaining portions of compressed packet in
+a field buff, saved character value is set at a position where zero
+char '\0' was inserted to enable a string do be zero delimited for
+mysql_use_result. Then a loop is started. In the first part of the
+loop, if there are remaining bytes, local uchar *pos variable is set
+at a current position in field buff where a new packet starts. This
+position is an (buf_length - remain_in_buf) offset in field buff. As
+it is possible that next logical packet is not read to the full length
+in the remaining of the field buf, several things had to be
+inspected. It should be noted that data that is read from
+net_rweal_read contains only logical packets containing 4 byte headers
+only, being 4 byte headers prepared by my_net_write or
+net_write_command. But, when written, logical packet could be so
+divided that only a part of header is read in. Therefore after pointer
+to the start of the next packet has been saved, a check is made
+whether number of remaining bytes in buffer is less then 4, being 3
+bytes for length and one byte for packet number. If it is greater,
+then a length of the logical packet is extracted and saved a length
+field. Then a check is made whether entire packet is contained withing
+a buf, i.e. a check is made that a logical packet is fully contained
+in a buffer. In that case, number of bytes remaining in buffer is
+decreased by a full length of logical packet ( 4 + length field),
+read_pos is moved forward by 4 bytes to skip header and be set at a
+beginning of data in logical packet, length field is saved for a value
+to be returned in function and a loop is exited. In a case that
+entire logical packet is not contained within a buffer, then if length
+of the entire buffer differs from remaining length of logical packet,
+it (logical packet) is moved to the beginning of the field buff. If
+length of the entire buffer equals the remaining length of logical
+packet, where_b and buf_length fields are set to 0. This is done so
+that in both cases buffer is ready to accept next part of packet. In
+order to get a next part of a packet, still within a loop,
+my_real_read function is called and length of compressed packet is
+returned to a local len variable, and length of compressed data is
+returned in complen variable. In a case of non-compression value of
+complen is zero. If packet_error is from my_real_read function, this
+function returns also with packet_error. If it is not a packet_error
+my_uncompress function is called to uncompress data. It is called with
+offset of where_b data from field buff, as it is a postion where
+compressed packet starts, and with len and complen values, being
+lengths of compressed and uncompressed data. If there is no
+compression, 0 is returned for uncompressed size from my_real_read
+function, and my_uncompress wrapper function is made to skip zlib
+uncompress in that case. If error is returned fom my_uncompress,
+error field is set to 1, if on server last_errno is set to
+ER_NET_UNCOMPRESS_ERROR and loop is exited and function returns with
+packet_error. If not, buf_length and reamin_in_buf fields are set to
+the uncompressed size of buffer and a loop is continued. When a loop
+is exited save_char field is used to save a char at end of a logical
+packet, which is an offset of field len from position in field buff
+pointed by field read_os, in order that zero char is set at the same
+position, for mysql_use_result. Function returns a length of the
+logical packet without it's header.