From c0941e427888b43460c85e58ab91b423844bb679 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 9 Aug 2005 10:22:48 -0700 Subject: Import zlib-1.2.3 library zlib/ChangeLog: Import zlib-1.2.3 zlib/FAQ: Import zlib-1.2.3 zlib/README: Import zlib-1.2.3 zlib/adler32.c: Import zlib-1.2.3 zlib/compress.c: Import zlib-1.2.3 zlib/crc32.c: Import zlib-1.2.3 zlib/deflate.c: Import zlib-1.2.3 zlib/deflate.h: Import zlib-1.2.3 zlib/gzio.c: Import zlib-1.2.3 zlib/infback.c: Import zlib-1.2.3 zlib/inffast.c: Import zlib-1.2.3 zlib/inflate.c: Import zlib-1.2.3 zlib/inflate.h: Import zlib-1.2.3 zlib/inftrees.c: Import zlib-1.2.3 zlib/inftrees.h: Import zlib-1.2.3 zlib/trees.c: Import zlib-1.2.3 zlib/zconf.h: Import zlib-1.2.3 zlib/zlib.3: Import zlib-1.2.3 zlib/zlib.h: Import zlib-1.2.3 zlib/zutil.c: Import zlib-1.2.3 zlib/zutil.h: Import zlib-1.2.3 zlib/README.MySQL: Import zlib-1.2.3 --- zlib/ChangeLog | 98 +++++++++++++++++-- zlib/FAQ | 26 ++--- zlib/README | 9 +- zlib/README.MySQL | 7 ++ zlib/adler32.c | 111 +++++++++++++++++---- zlib/compress.c | 2 +- zlib/crc32.c | 102 ++++++++++++++++++-- zlib/deflate.c | 282 +++++++++++++++++++++++++++++++++++++++++++++++++----- zlib/deflate.h | 10 +- zlib/gzio.c | 51 ++++++---- zlib/infback.c | 11 ++- zlib/inffast.c | 13 +++ zlib/inflate.c | 126 ++++++++++++++++++++---- zlib/inflate.h | 8 +- zlib/inftrees.c | 9 +- zlib/inftrees.h | 10 +- zlib/trees.c | 36 +++---- zlib/zconf.h | 12 ++- zlib/zlib.3 | 6 +- zlib/zlib.h | 229 +++++++++++++++++++++++++++++++++++++------- zlib/zutil.c | 33 ++++--- zlib/zutil.h | 30 +++--- 22 files changed, 1008 insertions(+), 213 deletions(-) create mode 100644 zlib/README.MySQL diff --git a/zlib/ChangeLog b/zlib/ChangeLog index 1af7633d668..7f6869d3235 100644 --- a/zlib/ChangeLog +++ b/zlib/ChangeLog @@ -1,10 +1,96 @@ ChangeLog file for zlib -Changes in port for MySQL (19 July 2004) -- removed contrib, nt, os2, amiga, directories and some other files not used -in MySQL distribution. If you are working on porting MySQL to one of rare -platforms, you might find worth looking at the original zlib distribution -and using appropriate Makefiles/project files from it. + +Changes in 1.2.3 (18 July 2005) +- Apply security vulnerability fixes to contrib/infback9 as well +- Clean up some text files (carriage returns, trailing space) +- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant] + +Changes in 1.2.2.4 (11 July 2005) +- Add inflatePrime() function for starting inflation at bit boundary +- Avoid some Visual C warnings in deflate.c +- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit + compile +- Fix some spelling errors in comments [Betts] +- Correct inflateInit2() error return documentation in zlib.h +- Added zran.c example of compressed data random access to examples + directory, shows use of inflatePrime() +- Fix cast for assignments to strm->state in inflate.c and infback.c +- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer] +- Move declarations of gf2 functions to right place in crc32.c [Oberhumer] +- Add cast in trees.c t avoid a warning [Oberhumer] +- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer] +- Update make_vms.com [Zinser] +- Initialize state->write in inflateReset() since copied in inflate_fast() +- Be more strict on incomplete code sets in inflate_table() and increase + ENOUGH and MAXD -- this repairs a possible security vulnerability for + invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for + discovering the vulnerability and providing test cases. +- Add ia64 support to configure for HP-UX [Smith] +- Add error return to gzread() for format or i/o error [Levin] +- Use malloc.h for OS/2 [Necasek] + +Changes in 1.2.2.3 (27 May 2005) +- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile +- Typecast fread() return values in gzio.c [Vollant] +- Remove trailing space in minigzip.c outmode (VC++ can't deal with it) +- Fix crc check bug in gzread() after gzungetc() [Heiner] +- Add the deflateTune() function to adjust internal compression parameters +- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack) +- Remove an incorrect assertion in examples/zpipe.c +- Add C++ wrapper in infback9.h [Donais] +- Fix bug in inflateCopy() when decoding fixed codes +- Note in zlib.h how much deflateSetDictionary() actually uses +- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used) +- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer] +- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer] +- Add gzdirect() function to indicate transparent reads +- Update contrib/minizip [Vollant] +- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer] +- Add casts in crc32.c to avoid warnings [Oberhumer] +- Add contrib/masmx64 [Vollant] +- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant] + +Changes in 1.2.2.2 (30 December 2004) +- Replace structure assignments in deflate.c and inflate.c with zmemcpy to + avoid implicit memcpy calls (portability for no-library compilation) +- Increase sprintf() buffer size in gzdopen() to allow for large numbers +- Add INFLATE_STRICT to check distances against zlib header +- Improve WinCE errno handling and comments [Chang] +- Remove comment about no gzip header processing in FAQ +- Add Z_FIXED strategy option to deflateInit2() to force fixed trees +- Add updated make_vms.com [Coghlan], update README +- Create a new "examples" directory, move gzappend.c there, add zpipe.c, + fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html. +- Add FAQ entry and comments in deflate.c on uninitialized memory access +- Add Solaris 9 make options in configure [Gilbert] +- Allow strerror() usage in gzio.c for STDC +- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] +- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] +- Use z_off_t for adler32_combine() and crc32_combine() lengths +- Make adler32() much faster for small len +- Use OS_CODE in deflate() default gzip header + +Changes in 1.2.2.1 (31 October 2004) +- Allow inflateSetDictionary() call for raw inflate +- Fix inflate header crc check bug for file names and comments +- Add deflateSetHeader() and gz_header structure for custom gzip headers +- Add inflateGetheader() to retrieve gzip headers +- Add crc32_combine() and adler32_combine() functions +- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list +- Use zstreamp consistently in zlib.h (inflate_back functions) +- Remove GUNZIP condition from definition of inflate_mode in inflate.h + and in contrib/inflate86/inffast.S [Truta, Anderson] +- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson] +- Update projects/README.projects and projects/visualc6 [Truta] +- Update win32/DLL_FAQ.txt [Truta] +- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta] +- Deprecate Z_ASCII; use Z_TEXT instead [Truta] +- Use a new algorithm for setting strm->data_type in trees.c [Truta] +- Do not define an exit() prototype in zutil.c unless DEBUG defined +- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] +- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() +- Fix Darwin build version identification [Peterson] Changes in 1.2.2 (3 October 2004) - Update zlib.h comments on gzip in-memory processing @@ -454,7 +540,7 @@ Changes in 1.0.7 (20 Jan 1998) Changes in 1.0.6 (19 Jan 1998) - add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) -- Fix a deflate bug occuring only with compression level 0 (thanks to +- Fix a deflate bug occurring only with compression level 0 (thanks to Andy Buckler for finding this one). - In minigzip, pass transparently also the first byte for .Z files. - return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() diff --git a/zlib/FAQ b/zlib/FAQ index 4f61f1094e6..441d910daa1 100644 --- a/zlib/FAQ +++ b/zlib/FAQ @@ -148,13 +148,6 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html format using deflateInit2(). You can also request that inflate decode the gzip format using inflateInit2(). Read zlib.h for more details. - Note that you cannot specify special gzip header contents (e.g. a file - name or modification date), nor will inflate tell you what was in the - gzip header. If you need to customize the header or see what's in it, - you can use the raw deflate and inflate operations and the crc32() - function and roll your own gzip encoding and decoding. Read the gzip - RFC 1952 for details of the header and trailer format. - 21. Is zlib thread-safe? Yes. However any library routines that zlib uses and any application- @@ -295,20 +288,29 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html were downright silly. So now, we simply make sure that the code always works. -36. Will zlib read the (insert any ancient or arcane format here) compressed +36. Valgrind (or some similar memory access checker) says that deflate is + performing a conditional jump that depends on an uninitialized value. + Isn't that a bug? + + No. That is intentional for performance reasons, and the output of + deflate is not affected. This only started showing up recently since + zlib 1.2.x uses malloc() by default for allocations, whereas earlier + versions used calloc(), which zeros out the allocated memory. + +37. Will zlib read the (insert any ancient or arcane format here) compressed data format? Probably not. Look in the comp.compression FAQ for pointers to various formats and associated software. -37. How can I encrypt/decrypt zip files with zlib? +38. How can I encrypt/decrypt zip files with zlib? zlib doesn't support encryption. The original PKZIP encryption is very weak and can be broken with freely available programs. To get strong encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib compression. For PKZIP compatible "encryption", look at http://www.info-zip.org/ -38. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? +39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? "gzip" is the gzip format, and "deflate" is the zlib format. They should probably have called the second one "zlib" instead to avoid confusion @@ -324,14 +326,14 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html Bottom line: use the gzip format for HTTP 1.1 encoding. -39. Does zlib support the new "Deflate64" format introduced by PKWare? +40. Does zlib support the new "Deflate64" format introduced by PKWare? No. PKWare has apparently decided to keep that format proprietary, since they have not documented it as they have previous compression formats. In any case, the compression improvements are so modest compared to other more modern approaches, that it's not worth the effort to implement. -40. Can you please sign these lengthy legal documents and fax them back to us +41. Can you please sign these lengthy legal documents and fax them back to us so that we can use your software in our product? No. Go away. Shoo. diff --git a/zlib/README b/zlib/README index df95ae13f54..758cc50020d 100644 --- a/zlib/README +++ b/zlib/README @@ -1,6 +1,6 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.2 is a general purpose data compression library. All the code is +zlib 1.2.3 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) @@ -16,9 +16,8 @@ minigzip.c. To compile all files and run the test program, follow the instructions given at the top of Makefile. In short "make test; make install" should work for most -machines. For Unix: "./configure; make test; make install" For MSDOS, use one -of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or -descrip.mms. +machines. For Unix: "./configure; make test; make install". For MSDOS, use one +of the special makefiles such as Makefile.msc. For VMS, use make_vms.com. Questions about zlib should be sent to , or to Gilles Vollant for the Windows DLL version. The zlib home page is @@ -34,7 +33,7 @@ Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available in http://dogma.net/markn/articles/zlibtool/zlibtool.htm -The changes made in version 1.2.2 are documented in the file ChangeLog. +The changes made in version 1.2.3 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory "contrib". diff --git a/zlib/README.MySQL b/zlib/README.MySQL new file mode 100644 index 00000000000..355dfb62d71 --- /dev/null +++ b/zlib/README.MySQL @@ -0,0 +1,7 @@ +This an incomplete version of the zlib library -- it excludes some of the +platform-specific project files, contributed code, and examples from the +original zlib distribution. You can find the original distribution at + + http://www.gzip.org/zlib/ + or + http://www.zlib.net/ diff --git a/zlib/adler32.c b/zlib/adler32.c index 624a1696eb0..007ba26277c 100644 --- a/zlib/adler32.c +++ b/zlib/adler32.c @@ -1,5 +1,5 @@ /* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2003 Mark Adler + * Copyright (C) 1995-2004 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -12,12 +12,13 @@ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ -#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); +/* use NO_DIVIDE if your processor does not do division in hardware */ #ifdef NO_DIVIDE # define MOD(a) \ do { \ @@ -39,8 +40,17 @@ if (a >= (BASE << 1)) a -= (BASE << 1); \ if (a >= BASE) a -= BASE; \ } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) #else # define MOD(a) a %= BASE +# define MOD4(a) a %= BASE #endif /* ========================================================================= */ @@ -49,26 +59,91 @@ uLong ZEXPORT adler32(adler, buf, len) const Bytef *buf; uInt len; { - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int k; + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } - if (buf == Z_NULL) return 1L; + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; - while (len > 0) { - k = len < NMAX ? (int)len : NMAX; - len -= k; - while (k >= 16) { + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; DO16(buf); buf += 16; - k -= 16; } - if (k != 0) do { - s1 += *buf++; - s2 += s1; - } while (--k); - MOD(s1); - MOD(s2); + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); } - return (s2 << 16) | s1; + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 > BASE) sum1 -= BASE; + if (sum1 > BASE) sum1 -= BASE; + if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 > BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); } diff --git a/zlib/compress.c b/zlib/compress.c index 24ef0291911..df04f0148e6 100644 --- a/zlib/compress.c +++ b/zlib/compress.c @@ -1,5 +1,5 @@ /* compress.c -- compress a memory buffer - * Copyright (C) 1995-2002 Jean-loup Gailly. + * Copyright (C) 1995-2003 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/zlib/crc32.c b/zlib/crc32.c index b39c7e1253e..f658a9ef55e 100644 --- a/zlib/crc32.c +++ b/zlib/crc32.c @@ -1,12 +1,12 @@ /* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2003 Mark Adler + * Copyright (C) 1995-2005 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results about a factor - * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. */ /* @(#) $Id$ */ @@ -64,6 +64,11 @@ # define TBLS 1 #endif /* BYFOUR */ +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); + #ifdef DYNAMIC_CRC_TABLE local volatile int crc_table_empty = 1; @@ -72,7 +77,6 @@ local void make_crc_table OF((void)); #ifdef MAKECRCH local void write_table OF((FILE *, const unsigned long FAR *)); #endif /* MAKECRCH */ - /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. @@ -270,7 +274,7 @@ local unsigned long crc32_little(crc, buf, len) len--; } - buf4 = (const u4 FAR *)buf; + buf4 = (const u4 FAR *)(const void FAR *)buf; while (len >= 32) { DOLIT32; len -= 32; @@ -310,7 +314,7 @@ local unsigned long crc32_big(crc, buf, len) len--; } - buf4 = (const u4 FAR *)buf; + buf4 = (const u4 FAR *)(const void FAR *)buf; buf4--; while (len >= 32) { DOBIG32; @@ -331,3 +335,89 @@ local unsigned long crc32_big(crc, buf, len) } #endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case */ + if (len2 == 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320L; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} diff --git a/zlib/deflate.c b/zlib/deflate.c index 0fc53bc1e82..29ce1f64a57 100644 --- a/zlib/deflate.c +++ b/zlib/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2004 Jean-loup Gailly. + * Copyright (C) 1995-2005 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.2 Copyright 1995-2004 Jean-loup Gailly "; + " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -264,7 +264,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, #endif if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_RLE) { + strategy < 0 || strategy > Z_FIXED) { return Z_STREAM_ERROR; } if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ @@ -274,6 +274,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, s->strm = strm; s->wrap = wrap; + s->gzhead = Z_NULL; s->w_bits = windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; @@ -333,9 +334,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) if (length < MIN_MATCH) return Z_OK; if (length > MAX_DIST(s)) { length = MAX_DIST(s); -#ifndef USE_DICT_HEAD dictionary += dictLength - length; /* use the tail of the dictionary */ -#endif } zmemcpy(s->window, dictionary, length); s->strstart = length; @@ -390,6 +389,17 @@ int ZEXPORT deflateReset (strm) return Z_OK; } +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + /* ========================================================================= */ int ZEXPORT deflatePrime (strm, bits, value) z_streamp strm; @@ -420,7 +430,7 @@ int ZEXPORT deflateParams(strm, level, strategy) #else if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif - if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) { + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { return Z_STREAM_ERROR; } func = configuration_table[s->level].func; @@ -440,6 +450,25 @@ int ZEXPORT deflateParams(strm, level, strategy) return err; } +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + /* ========================================================================= * For the default windowBits of 15 and memLevel of 8, this function returns * a close to exact, as well as small, upper bound on the compressed size. @@ -548,20 +577,47 @@ int ZEXPORT deflate (strm, flush) if (s->status == INIT_STATE) { #ifdef GZIP if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); put_byte(s, 31); put_byte(s, 139); put_byte(s, 8); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, 255); - s->status = BUSY_STATE; - strm->adler = crc32(0L, Z_NULL, 0); + if (s->gzhead == NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } } else #endif @@ -592,6 +648,110 @@ int ZEXPORT deflate (strm, flush) strm->adler = adler32(0L, Z_NULL, 0); } } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif /* Flush as much pending output as possible */ if (s->pending != 0) { @@ -704,7 +864,12 @@ int ZEXPORT deflateEnd (strm) if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; status = strm->state->status; - if (status != INIT_STATE && status != BUSY_STATE && + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && status != FINISH_STATE) { return Z_STREAM_ERROR; } @@ -744,12 +909,12 @@ int ZEXPORT deflateCopy (dest, source) ss = source->state; - *dest = *source; + zmemcpy(dest, source, sizeof(z_stream)); ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); if (ds == Z_NULL) return Z_MEM_ERROR; dest->state = (struct internal_state FAR *) ds; - *ds = *ss; + zmemcpy(ds, ss, sizeof(deflate_state)); ds->strm = dest; ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); @@ -838,9 +1003,11 @@ local void lm_init (s) s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; +#ifndef FASTEST #ifdef ASMV match_init(); /* initialize the asm code */ #endif +#endif } #ifndef FASTEST @@ -909,7 +1076,12 @@ local uInt longest_match(s, cur_match) match = s->window + cur_match; /* Skip to next match if the match length cannot increase - * or if the match length is less than 2: + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. */ #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) /* This code assumes sizeof(unsigned short) == 2. Do not use @@ -1131,6 +1303,7 @@ local void fill_window(s) later. (Using level 0 permanently is not an optimal usage of zlib, so we don't care about this pathological case.) */ + /* %%% avoid this when Z_RLE */ n = s->hash_size; p = &s->head[n]; do { @@ -1309,12 +1482,12 @@ local block_state deflate_fast(s, flush) * of the string with itself at the start of the input file). */ #ifdef FASTEST - if ((s->strategy < Z_HUFFMAN_ONLY) || + if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { s->match_length = longest_match_fast (s, hash_head); } #else - if (s->strategy < Z_HUFFMAN_ONLY) { + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { s->match_length = longest_match (s, hash_head); } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { s->match_length = longest_match_fast (s, hash_head); @@ -1418,7 +1591,7 @@ local block_state deflate_slow(s, flush) * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ - if (s->strategy < Z_HUFFMAN_ONLY) { + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { s->match_length = longest_match (s, hash_head); } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { s->match_length = longest_match_fast (s, hash_head); @@ -1500,3 +1673,64 @@ local block_state deflate_slow(s, flush) return flush == Z_FINISH ? finish_done : block_done; } #endif /* FASTEST */ + +#if 0 +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt run; /* length of run */ + uInt max; /* maximum length of run */ + uInt prev; /* byte at distance one to match */ + Bytef *scan; /* scan for end of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + run = 0; + if (s->strstart > 0) { /* if there is a previous byte, that is */ + max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; + scan = s->window + s->strstart - 1; + prev = *scan++; + do { + if (*scan++ != prev) + break; + } while (++run < max); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (run >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, run); + _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); + s->lookahead -= run; + s->strstart += run; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif diff --git a/zlib/deflate.h b/zlib/deflate.h index 410681d18a4..05a5ab3a2c1 100644 --- a/zlib/deflate.h +++ b/zlib/deflate.h @@ -1,5 +1,5 @@ /* deflate.h -- internal compression state - * Copyright (C) 1995-2002 Jean-loup Gailly + * Copyright (C) 1995-2004 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -49,6 +49,10 @@ /* All codes must not exceed MAX_BITS bits */ #define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 #define BUSY_STATE 113 #define FINISH_STATE 666 /* Stream status */ @@ -93,8 +97,10 @@ typedef struct internal_state { Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ - int pending; /* nb of bytes in the pending buffer */ + uInt pending; /* nb of bytes in the pending buffer */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ Byte method; /* STORED (for zip only) or DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ diff --git a/zlib/gzio.c b/zlib/gzio.c index 5e71b0ab3ae..7e90f4928fc 100644 --- a/zlib/gzio.c +++ b/zlib/gzio.c @@ -1,5 +1,5 @@ /* gzio.c -- IO on .gz files - * Copyright (C) 1995-2003 Jean-loup Gailly. + * Copyright (C) 1995-2005 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h * * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. @@ -11,7 +11,7 @@ #include "zutil.h" -#ifdef NO_DEFLATE /* for compatiblity with old definition */ +#ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif @@ -220,7 +220,7 @@ gzFile ZEXPORT gzdopen (fd, mode) int fd; const char *mode; { - char name[20]; + char name[46]; /* allow for up to 128-bit integers */ if (fd < 0) return (gzFile)Z_NULL; sprintf(name, "", fd); /* for debugging */ @@ -264,7 +264,7 @@ local int get_byte(s) if (s->z_eof) return EOF; if (s->stream.avail_in == 0) { errno = 0; - s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); if (s->stream.avail_in == 0) { s->z_eof = 1; if (ferror(s->file)) s->z_err = Z_ERRNO; @@ -300,7 +300,7 @@ local void check_header(s) if (len < 2) { if (len) s->inbuf[0] = s->stream.next_in[0]; errno = 0; - len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; s->stream.avail_in += len; s->stream.next_in = s->inbuf; @@ -415,6 +415,7 @@ int ZEXPORT gzread (file, buf, len) s->stream.avail_out--; s->back = EOF; s->out++; + start++; if (s->last) { s->z_err = Z_STREAM_END; return 1; @@ -436,8 +437,8 @@ int ZEXPORT gzread (file, buf, len) s->stream.avail_in -= n; } if (s->stream.avail_out > 0) { - s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, - s->file); + s->stream.avail_out -= + (uInt)fread(next_out, 1, s->stream.avail_out, s->file); } len -= s->stream.avail_out; s->in += len; @@ -448,17 +449,13 @@ int ZEXPORT gzread (file, buf, len) if (s->stream.avail_in == 0 && !s->z_eof) { errno = 0; - s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); if (s->stream.avail_in == 0) { s->z_eof = 1; if (ferror(s->file)) { s->z_err = Z_ERRNO; break; } - if (feof(s->file)) { /* avoid error for empty file */ - s->z_err = Z_STREAM_END; - break; - } } s->stream.next_in = s->inbuf; } @@ -492,6 +489,9 @@ int ZEXPORT gzread (file, buf, len) } s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + if (len == s->stream.avail_out && + (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) + return -1; return (int)(len - s->stream.avail_out); } @@ -902,6 +902,18 @@ int ZEXPORT gzeof (file) return s->z_err == Z_STREAM_END; } +/* =========================================================================== + Returns 1 if reading and doing so transparently, otherwise zero. +*/ +int ZEXPORT gzdirect (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return 0; + return s->transparent; +} + /* =========================================================================== Outputs a long in LSB order to the given file */ @@ -941,7 +953,6 @@ local uLong getLong (s) int ZEXPORT gzclose (file) gzFile file; { - int err; gz_stream *s = (gz_stream*)file; if (s == NULL) return Z_STREAM_ERROR; @@ -950,8 +961,8 @@ int ZEXPORT gzclose (file) #ifdef NO_GZCOMPRESS return Z_STREAM_ERROR; #else - err = do_flush (file, Z_FINISH); - if (err != Z_OK) return destroy((gz_stream*)file); + if (do_flush (file, Z_FINISH) != Z_OK) + return destroy((gz_stream*)file); putLong (s->file, s->crc); putLong (s->file, (uLong)(s->in & 0xffffffff)); @@ -960,10 +971,16 @@ int ZEXPORT gzclose (file) return destroy((gz_stream*)file); } +#ifdef STDC +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + /* =========================================================================== - Returns the error message for the last error which occured on the + Returns the error message for the last error which occurred on the given compressed file. errnum is set to zlib error number. If an - error occured in the file system and not in the compression library, + error occurred in the file system and not in the compression library, errnum is set to Z_ERRNO and the application may consult errno to get the exact error code. */ diff --git a/zlib/infback.c b/zlib/infback.c index 262f97c73ac..455dbc9ee84 100644 --- a/zlib/infback.c +++ b/zlib/infback.c @@ -1,5 +1,5 @@ /* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2003 Mark Adler + * Copyright (C) 1995-2005 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -26,7 +26,7 @@ local void fixedtables OF((struct inflate_state FAR *state)); window and output buffer that is 2**windowBits bytes. */ int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) -z_stream FAR *strm; +z_streamp strm; int windowBits; unsigned char FAR *window; const char *version; @@ -50,7 +50,8 @@ int stream_size; sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); - strm->state = (voidpf)state; + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; state->wbits = windowBits; state->wsize = 1U << windowBits; state->window = window; @@ -238,7 +239,7 @@ struct inflate_state FAR *state; are not correct, i.e. strm is Z_NULL or the state was not initialized. */ int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) -z_stream FAR *strm; +z_streamp strm; in_func in; void FAR *in_desc; out_func out; @@ -611,7 +612,7 @@ void FAR *out_desc; } int ZEXPORT inflateBackEnd(strm) -z_stream FAR *strm; +z_streamp strm; { if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; diff --git a/zlib/inffast.c b/zlib/inffast.c index 8c02a178d04..bbee92ed1e6 100644 --- a/zlib/inffast.c +++ b/zlib/inffast.c @@ -74,6 +74,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned write; /* window write index */ @@ -98,6 +101,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ out = strm->next_out - OFF; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif wsize = state->wsize; whave = state->whave; write = state->write; @@ -167,6 +173,13 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ } } dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif hold >>= op; bits -= op; Tracevv((stderr, "inflate: distance %u\n", dist)); diff --git a/zlib/inflate.c b/zlib/inflate.c index c6d38266d07..792fdee8e9c 100644 --- a/zlib/inflate.c +++ b/zlib/inflate.c @@ -1,5 +1,5 @@ /* inflate.c -- zlib decompression - * Copyright (C) 1995-2003 Mark Adler + * Copyright (C) 1995-2005 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -113,8 +113,11 @@ z_streamp strm; state->mode = HEAD; state->last = 0; state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; state->wsize = 0; state->whave = 0; + state->write = 0; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; @@ -122,6 +125,22 @@ z_streamp strm; return Z_OK; } +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) z_streamp strm; int windowBits; @@ -144,7 +163,7 @@ int stream_size; ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); - strm->state = (voidpf)state; + strm->state = (struct internal_state FAR *)state; if (windowBits < 0) { state->wrap = 0; windowBits = -windowBits; @@ -582,6 +601,8 @@ int flush; break; } state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; if (!(state->wrap & 1) || /* check if zlib header allowed */ #else if ( @@ -597,11 +618,13 @@ int flush; break; } DROPBITS(4); - if (BITS(4) + 8 > state->wbits) { + len = BITS(4) + 8; + if (len > state->wbits) { strm->msg = (char *)"invalid window size"; state->mode = BAD; break; } + state->dmax = 1U << len; Tracev((stderr, "inflate: zlib header ok\n")); strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = hold & 0x200 ? DICTID : TYPE; @@ -621,16 +644,24 @@ int flush; state->mode = BAD; break; } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); state->mode = TIME; case TIME: NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; if (state->flags & 0x0200) CRC4(state->check, hold); INITBITS(); state->mode = OS; case OS: NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; @@ -638,15 +669,26 @@ int flush; if (state->flags & 0x0400) { NEEDBITS(16); state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; state->mode = EXTRA; case EXTRA: if (state->flags & 0x0400) { copy = state->length; if (copy > have) copy = have; if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; @@ -655,6 +697,7 @@ int flush; } if (state->length) goto inf_leave; } + state->length = 0; state->mode = NAME; case NAME: if (state->flags & 0x0800) { @@ -662,13 +705,20 @@ int flush; copy = 0; do { len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; } while (len && copy < have); - if (state->flags & 0x02000) + if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; state->mode = COMMENT; case COMMENT: if (state->flags & 0x1000) { @@ -676,13 +726,19 @@ int flush; copy = 0; do { len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; } while (len && copy < have); - if (state->flags & 0x02000) + if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; state->mode = HCRC; case HCRC: if (state->flags & 0x0200) { @@ -694,6 +750,10 @@ int flush; } INITBITS(); } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } strm->adler = state->check = crc32(0L, Z_NULL, 0); state->mode = TYPE; break; @@ -969,6 +1029,13 @@ int flush; state->offset += BITS(state->extra); DROPBITS(state->extra); } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif if (state->offset > state->whave + out - left) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; @@ -1110,12 +1177,16 @@ uInt dictLength; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; - if (state->mode != DICT) return Z_STREAM_ERROR; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; /* check for correct dictionary id */ - id = adler32(0L, Z_NULL, 0); - id = adler32(id, dictionary, dictLength); - if (id != state->check) return Z_DATA_ERROR; + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } /* copy dictionary to window */ if (updatewindow(strm, strm->avail_out)) { @@ -1137,6 +1208,23 @@ uInt dictLength; return Z_OK; } +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + /* Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found or when out of input. When called, *have is the number of pattern bytes @@ -1239,6 +1327,7 @@ z_streamp source; struct inflate_state FAR *state; struct inflate_state FAR *copy; unsigned char FAR *window; + unsigned wsize; /* check input */ if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || @@ -1261,14 +1350,19 @@ z_streamp source; } /* copy state */ - *dest = *source; - *copy = *state; - copy->lencode = copy->codes + (state->lencode - state->codes); - copy->distcode = copy->codes + (state->distcode - state->codes); + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } copy->next = copy->codes + (state->next - state->codes); - if (window != Z_NULL) - zmemcpy(window, state->window, 1U << state->wbits); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } copy->window = window; - dest->state = (voidpf)copy; + dest->state = (struct internal_state FAR *)copy; return Z_OK; } diff --git a/zlib/inflate.h b/zlib/inflate.h index 9a12c8fd296..07bd3e78a7c 100644 --- a/zlib/inflate.h +++ b/zlib/inflate.h @@ -1,5 +1,5 @@ /* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2003 Mark Adler + * Copyright (C) 1995-2004 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -19,7 +19,6 @@ /* Possible inflate modes between inflate() calls */ typedef enum { HEAD, /* i: waiting for magic header */ -#ifdef GUNZIP FLAGS, /* i: waiting for method and flags (gzip) */ TIME, /* i: waiting for modification time (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */ @@ -28,7 +27,6 @@ typedef enum { NAME, /* i: waiting for end of file name (gzip) */ COMMENT, /* i: waiting for end of comment (gzip) */ HCRC, /* i: waiting for header crc (gzip) */ -#endif DICTID, /* i: waiting for dictionary check value */ DICT, /* waiting for inflateSetDictionary() call */ TYPE, /* i: waiting for type bits, including last-flag bit */ @@ -45,9 +43,7 @@ typedef enum { MATCH, /* o: waiting for output space to copy string */ LIT, /* o: waiting for output space to write literal */ CHECK, /* i: waiting for 32-bit check value */ -#ifdef GUNZIP LENGTH, /* i: waiting for 32-bit length (gzip) */ -#endif DONE, /* finished check, done -- remain here until reset */ BAD, /* got a data error -- remain here until reset */ MEM, /* got an inflate() memory error -- remain here until reset */ @@ -84,8 +80,10 @@ struct inflate_state { int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ int havedict; /* true if dictionary provided */ int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ unsigned long check; /* protected copy of check value */ unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ /* sliding window */ unsigned wbits; /* log base 2 of requested window size */ unsigned wsize; /* window size or zero if not using window */ diff --git a/zlib/inftrees.c b/zlib/inftrees.c index 509461d9273..8a9c13ff03d 100644 --- a/zlib/inftrees.c +++ b/zlib/inftrees.c @@ -1,5 +1,5 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2004 Mark Adler + * Copyright (C) 1995-2005 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.2 Copyright 1995-2004 Mark Adler "; + " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -62,7 +62,7 @@ unsigned short FAR *work; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 198}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, @@ -232,6 +232,7 @@ unsigned short FAR *work; /* replicate for those indices with low len bits equal to huff */ incr = 1U << (len - drop); fill = 1U << curr; + min = fill; /* save offset to next table */ do { fill -= incr; next[(huff >> drop) + fill] = this; @@ -262,7 +263,7 @@ unsigned short FAR *work; drop = root; /* increment past last table */ - next += 1U << curr; + next += min; /* here min is 1 << curr */ /* determine length of next table */ curr = len - drop; diff --git a/zlib/inftrees.h b/zlib/inftrees.h index 82d365a7e90..b1104c87e76 100644 --- a/zlib/inftrees.h +++ b/zlib/inftrees.h @@ -1,5 +1,5 @@ /* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2003 Mark Adler + * Copyright (C) 1995-2005 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -36,12 +36,12 @@ typedef struct { */ /* Maximum size of dynamic tree. The maximum found in a long but non- - exhaustive search was 1004 code structures (850 for length/literals - and 154 for distances, the latter actually the result of an + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an exhaustive search). The true maximum is not known, but the value below is more than safe. */ -#define ENOUGH 1440 -#define MAXD 154 +#define ENOUGH 2048 +#define MAXD 592 /* Type of code to build for inftable() */ typedef enum { diff --git a/zlib/trees.c b/zlib/trees.c index 52c820fa2e9..395e4e16814 100644 --- a/zlib/trees.c +++ b/zlib/trees.c @@ -1,5 +1,5 @@ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2003 Jean-loup Gailly + * Copyright (C) 1995-2005 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -555,7 +555,7 @@ local void gen_bitlen(s, desc) while (n != 0) { m = s->heap[--h]; if (m > max_code) continue; - if (tree[m].Len != (unsigned) bits) { + if ((unsigned) tree[m].Len != (unsigned) bits) { Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); s->opt_len += ((long)bits - (long)tree[m].Len) *(long)tree[m].Freq; @@ -930,8 +930,9 @@ void _tr_flush_block(s, buf, stored_len, eof) /* Build the Huffman trees unless a stored block is forced */ if (s->level > 0) { - /* Check if the file is ascii or binary */ - if (s->strm->data_type == Z_UNKNOWN) set_data_type(s); + /* Check if the file is binary or text */ + if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) + set_data_type(s); /* Construct the literal and distance trees */ build_tree(s, (tree_desc *)(&(s->l_desc))); @@ -982,7 +983,7 @@ void _tr_flush_block(s, buf, stored_len, eof) #ifdef FORCE_STATIC } else if (static_lenb >= 0) { /* force static trees */ #else - } else if (static_lenb == opt_lenb) { + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { #endif send_bits(s, (STATIC_TREES<<1)+eof, 3); compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); @@ -1117,21 +1118,24 @@ local void compress_block(s, ltree, dtree) } /* =========================================================================== - * Set the data type to ASCII or BINARY, using a crude approximation: - * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. - * IN assertion: the fields freq of dyn_ltree are set and the total of all - * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + * Set the data type to BINARY or TEXT, using a crude approximation: + * set it to Z_TEXT if all symbols are either printable characters (33 to 255) + * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise. + * IN assertion: the fields Freq of dyn_ltree are set. */ local void set_data_type(s) deflate_state *s; { - int n = 0; - unsigned ascii_freq = 0; - unsigned bin_freq = 0; - while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; - while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; - while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; - s->strm->data_type = bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII; + int n; + + for (n = 0; n < 9; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + if (n == 9) + for (n = 14; n < 32; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; } /* =========================================================================== diff --git a/zlib/zconf.h b/zlib/zconf.h index 3c21403fce6..03a9431c8be 100644 --- a/zlib/zconf.h +++ b/zlib/zconf.h @@ -1,5 +1,5 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2004 Jean-loup Gailly. + * Copyright (C) 1995-2005 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -43,6 +43,10 @@ # define get_crc_table z_get_crc_table # define zError z_zError +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func # define Byte z_Byte # define uInt z_uInt # define uLong z_uLong @@ -64,8 +68,10 @@ #if defined(_WINDOWS) && !defined(WINDOWS) # define WINDOWS #endif -#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) -# define WIN32 +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif #endif #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) diff --git a/zlib/zlib.3 b/zlib/zlib.3 index 3139e2467f2..90b8162870f 100644 --- a/zlib/zlib.3 +++ b/zlib/zlib.3 @@ -1,4 +1,4 @@ -.TH ZLIB 3 "3 October 2004" +.TH ZLIB 3 "18 July 2005" .SH NAME zlib \- compression/decompression library .SH SYNOPSIS @@ -133,8 +133,8 @@ before asking for help. Send questions and/or comments to zlib@gzip.org, or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). .SH AUTHORS -Version 1.2.2 -Copyright (C) 1995-2004 Jean-loup Gailly (jloup@gzip.org) +Version 1.2.3 +Copyright (C) 1995-2005 Jean-loup Gailly (jloup@gzip.org) and Mark Adler (madler@alumni.caltech.edu). .LP This software is provided "as-is," diff --git a/zlib/zlib.h b/zlib/zlib.h index b4ddd34395c..022817927ce 100644 --- a/zlib/zlib.h +++ b/zlib/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.2, October 3rd, 2004 + version 1.2.3, July 18th, 2005 - Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -37,8 +37,8 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.2" -#define ZLIB_VERNUM 0x1220 +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 /* The 'zlib' compression library provides in-memory compression and @@ -95,13 +95,36 @@ typedef struct z_stream_s { free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ - int data_type; /* best guess about the data type: ascii or binary */ + int data_type; /* best guess about the data type: binary or text */ uLong adler; /* adler32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + /* The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out @@ -166,11 +189,13 @@ typedef z_stream FAR *z_streamp; #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_RLE 3 +#define Z_FIXED 4 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 -#define Z_ASCII 1 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 /* Possible values of the data_type field (though see inflate()) */ @@ -244,6 +269,10 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular @@ -255,7 +284,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - the compression. + compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated @@ -280,8 +309,8 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); deflate() sets strm->adler to the adler32 checksum of all input read so far (that is, total_in bytes). - deflate() may update data_type if it can make a good guess about - the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. @@ -363,11 +392,11 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much output as possible to the output buffer. Z_BLOCK requests that inflate() stop - if and when it get to the next deflate block boundary. When decoding the zlib - or gzip format, this will cause inflate() to return immediately after the - header and before the first block. When doing a raw inflate, inflate() will - go ahead and process the first block, and will return when it gets to the end - of that block, or when it runs out of data. + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. Also to assist in this, on return inflate() will set strm->data_type to the @@ -496,7 +525,9 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy parameter only affects the compression ratio but not the correctness of the - compressed output even if it is not set appropriately. + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid @@ -525,7 +556,9 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, deflateInit or deflateInit2, a part of the dictionary may in effect be discarded, for example if the dictionary is larger than the window size in deflate or deflate2. Thus the strings most likely to be useful should be - put at the end of the dictionary, not at the front. + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. Upon return of this function, strm->adler is set to the adler32 value of the dictionary; the decompressor may later use this value to determine @@ -591,6 +624,23 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, if strm->avail_out was zero. */ +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, uLong sourceLen)); /* @@ -616,6 +666,30 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, stream state was inconsistent. */ +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + /* ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, int windowBits)); @@ -648,15 +722,15 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, windowBits can also be greater than 15 for optional gzip decoding. Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR. If a gzip stream is being decoded, strm->adler is + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a crc32 instead of an adler32. inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative - memLevel). msg is set to null if there is no error message. inflateInit2 - does not perform any decompression apart from reading the zlib header if - present: this will be done by inflate(). (So next_in and avail_in may be - modified, but next_out and avail_out are unchanged.) + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) */ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, @@ -664,11 +738,14 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, uInt dictLength)); /* Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate - if this call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by this call of - inflate. The compressor and decompressor must use exactly the same - dictionary (see deflateSetDictionary). + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (such as NULL dictionary) or the stream state is @@ -719,8 +796,64 @@ ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); stream state was inconsistent (such as zalloc or state being NULL). */ +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + /* -ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, unsigned char FAR *window)); Initialize the internal stream state for decompression using inflateBack() @@ -744,7 +877,7 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); -ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc)); /* @@ -813,7 +946,7 @@ ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, that inflateBack() cannot return Z_OK. */ -ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); /* All memory allocated by inflateBackInit() is freed. @@ -1087,6 +1220,12 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); input stream, otherwise zero. */ +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + ZEXTERN int ZEXPORT gzclose OF((gzFile file)); /* Flushes all pending output if necessary, closes the compressed file @@ -1119,7 +1258,6 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); */ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); - /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. If buf is NULL, this function returns @@ -1135,12 +1273,21 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); if (adler != original_adler) error(); */ +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); /* - Update a running crc with the bytes buf[0..len-1] and return the updated - crc. If buf is NULL, this function returns the required initial value - for the crc. Pre- and post-conditioning (one's complement) is performed - within this function so it shouldn't be done by the application. + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. Usage example: uLong crc = crc32(0L, Z_NULL, 0); @@ -1151,6 +1298,16 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); if (crc != original_crc) error(); */ +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + /* various hacks, don't look :) */ @@ -1167,7 +1324,7 @@ ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, int stream_size)); ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)); diff --git a/zlib/zutil.c b/zlib/zutil.c index 0ef4f99f57e..d55f5948a37 100644 --- a/zlib/zutil.c +++ b/zlib/zutil.c @@ -1,5 +1,5 @@ /* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2003 Jean-loup Gailly. + * Copyright (C) 1995-2005 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -11,10 +11,6 @@ struct internal_state {int dummy;}; /* for buggy compilers */ #endif -#ifndef STDC -extern void exit OF((int)); -#endif - const char * const z_errmsg[10] = { "need dictionary", /* Z_NEED_DICT 2 */ "stream end", /* Z_STREAM_END 1 */ @@ -78,38 +74,38 @@ uLong ZEXPORT zlibCompileFlags() flags += 1 << 13; #endif #ifdef NO_GZCOMPRESS - flags += 1 << 16; + flags += 1L << 16; #endif #ifdef NO_GZIP - flags += 1 << 17; + flags += 1L << 17; #endif #ifdef PKZIP_BUG_WORKAROUND - flags += 1 << 20; + flags += 1L << 20; #endif #ifdef FASTEST - flags += 1 << 21; + flags += 1L << 21; #endif #ifdef STDC # ifdef NO_vsnprintf - flags += 1 << 25; + flags += 1L << 25; # ifdef HAS_vsprintf_void - flags += 1 << 26; + flags += 1L << 26; # endif # else # ifdef HAS_vsnprintf_void - flags += 1 << 26; + flags += 1L << 26; # endif # endif #else - flags += 1 << 24; + flags += 1L << 24; # ifdef NO_snprintf - flags += 1 << 25; + flags += 1L << 25; # ifdef HAS_sprintf_void - flags += 1 << 26; + flags += 1L << 26; # endif # else # ifdef HAS_snprintf_void - flags += 1 << 26; + flags += 1L << 26; # endif # endif #endif @@ -141,7 +137,10 @@ const char * ZEXPORT zError(err) } #if defined(_WIN32_WCE) - /* does not exist on WCE */ + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ int errno = 0; #endif diff --git a/zlib/zutil.h b/zlib/zutil.h index 7b42edcaa98..b7d5eff81b6 100644 --- a/zlib/zutil.h +++ b/zlib/zutil.h @@ -1,5 +1,5 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2003 Jean-loup Gailly. + * Copyright (C) 1995-2005 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -17,14 +17,26 @@ #include "zlib.h" #ifdef STDC -# include +# ifndef _WIN32_WCE +# include +# endif # include # include #endif #ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif extern int errno; #else -# include +# ifndef _WIN32_WCE +# include +# endif #endif #ifndef local @@ -105,6 +117,9 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #ifdef OS2 # define OS_CODE 0x06 +# ifdef M_I86 + #include +# endif #endif #if defined(MACOS) || defined(TARGET_OS_MAC) @@ -193,15 +208,6 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # define NO_vsnprintf #endif -#ifdef HAVE_STRERROR -# ifndef VMS - extern char *strerror OF((int)); -# endif -# define zstrerror(errnum) strerror(errnum) -#else -# define zstrerror(errnum) "" -#endif - #if defined(pyr) # define NO_MEMCPY #endif -- cgit v1.2.1 From 8e7217e43bed6db3bffd97a39b85c65e1a72579a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Sep 2005 09:49:19 +0300 Subject: Fix for BUG#12882 - min/max inconsistent on empty table. The problem was in that the MIN/MAX optimization in opt_sum_query was replacing MIN/MAX functions with their constant argument without taking into account that a query has no result rows. mysql-test/r/func_group.result: Test for BUG#12882. mysql-test/t/func_group.test: Test for BUG#12882. sql/item_sum.cc: If it is known that a query has no result rows, do not call add() via the call to Item_sum::no_rows_in_result() which calls reset(). Instead directly call clear() so that the MIN and MAX functions produce NULL when there are no result rows. sql/opt_sum.cc: * Do not apply MIN/MAX optimization when the operand of MIN/MAX is a constant if it can't be determined whether the query has any result rows. The reason is that if the query has result rows, then the result of MIN/MAX is its constant argument, but if the query result is empty, then the result of MIN/MAX must be NULL irrespective of its argument. * The patch also simplifies a bit the branch that hadles COUNT(). --- mysql-test/r/func_group.result | 136 +++++++++++++++++++++++++++++++++++++++++ mysql-test/t/func_group.test | 69 +++++++++++++++++++++ sql/item_sum.cc | 2 +- sql/opt_sum.cc | 96 ++++++++++++++++++++--------- 4 files changed, 273 insertions(+), 30 deletions(-) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index 2fb18ca92c7..67966b999d4 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -780,3 +780,139 @@ SELECT MAX(id) FROM t1 WHERE id < 3 AND a=2 AND b=6; MAX(id) NULL DROP TABLE t1; +create table t1m (a int) engine=myisam; +create table t1i (a int) engine=innodb; +create table t2m (a int) engine=myisam; +create table t2i (a int) engine=innodb; +insert into t2m values (5); +insert into t2i values (5); +select min(a) from t1m; +min(a) +NULL +select min(7) from t1m; +min(7) +NULL +select min(7) from DUAL; +min(7) +NULL +explain select min(7) from t2m join t1m; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +select min(7) from t2m join t1m; +min(7) +NULL +select max(a) from t1m; +max(a) +NULL +select max(7) from t1m; +max(7) +NULL +select max(7) from DUAL; +max(7) +NULL +explain select max(7) from t2m join t1m; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +select max(7) from t2m join t1m; +max(7) +NULL +select 1, min(a) from t1m where a=99; +1 min(a) +1 NULL +select 1, min(a) from t1m where 1=99; +1 min(a) +1 NULL +select 1, min(1) from t1m where a=99; +1 min(1) +select 1, min(1) from t1m where 1=99; +1 min(1) +1 NULL +select 1, max(a) from t1m where a=99; +1 max(a) +1 NULL +select 1, max(a) from t1m where 1=99; +1 max(a) +1 NULL +select 1, max(1) from t1m where a=99; +1 max(1) +select 1, max(1) from t1m where 1=99; +1 max(1) +1 NULL +select min(a) from t1i; +min(a) +NULL +select min(7) from t1i; +min(7) +NULL +select min(7) from DUAL; +min(7) +NULL +explain select min(7) from t2i join t1i; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2i ALL NULL NULL NULL NULL 1 +1 SIMPLE t1i ALL NULL NULL NULL NULL 1 +select min(7) from t2i join t1i; +min(7) +NULL +select max(a) from t1i; +max(a) +NULL +select max(7) from t1i; +max(7) +NULL +select max(7) from DUAL; +max(7) +NULL +explain select max(7) from t2i join t1i; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2i ALL NULL NULL NULL NULL 1 +1 SIMPLE t1i ALL NULL NULL NULL NULL 1 +select max(7) from t2i join t1i; +max(7) +NULL +select 1, min(a) from t1i where a=99; +1 min(a) +1 NULL +select 1, min(a) from t1i where 1=99; +1 min(a) +1 NULL +select 1, min(1) from t1i where a=99; +1 min(1) +1 NULL +select 1, min(1) from t1i where 1=99; +1 min(1) +1 NULL +select 1, max(a) from t1i where a=99; +1 max(a) +1 NULL +select 1, max(a) from t1i where 1=99; +1 max(a) +1 NULL +select 1, max(1) from t1i where a=99; +1 max(1) +1 NULL +select 1, max(1) from t1i where 1=99; +1 max(1) +1 NULL +explain select count(*), min(7), max(7) from t1m, t1i; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t1i ALL NULL NULL NULL NULL 1 +select count(*), min(7), max(7) from t1m, t1i; +count(*) min(7) max(7) +0 NULL NULL +explain select count(*), min(7), max(7) from t1m, t2i; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t2i ALL NULL NULL NULL NULL 1 +select count(*), min(7), max(7) from t1m, t2i; +count(*) min(7) max(7) +0 NULL NULL +explain select count(*), min(7), max(7) from t2m, t1i; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2m system NULL NULL NULL NULL 1 +1 SIMPLE t1i ALL NULL NULL NULL NULL 1 +select count(*), min(7), max(7) from t2m, t1i; +count(*) min(7) max(7) +0 NULL NULL +drop table t1m, t1i, t2m, t2i; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index 4dc8d66c4f1..f833f482f73 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -527,4 +527,73 @@ INSERT INTO t1 VALUES SELECT MAX(id) FROM t1 WHERE id < 3 AND a=2 AND b=6; DROP TABLE t1; +# +# Bug #12882 min/max inconsistent on empty table +# + +create table t1m (a int) engine=myisam; +create table t1i (a int) engine=innodb; +create table t2m (a int) engine=myisam; +create table t2i (a int) engine=innodb; +insert into t2m values (5); +insert into t2i values (5); + +# test with MyISAM +select min(a) from t1m; +select min(7) from t1m; +select min(7) from DUAL; +explain select min(7) from t2m join t1m; +select min(7) from t2m join t1m; + +select max(a) from t1m; +select max(7) from t1m; +select max(7) from DUAL; +explain select max(7) from t2m join t1m; +select max(7) from t2m join t1m; + +select 1, min(a) from t1m where a=99; +select 1, min(a) from t1m where 1=99; +select 1, min(1) from t1m where a=99; +select 1, min(1) from t1m where 1=99; + +select 1, max(a) from t1m where a=99; +select 1, max(a) from t1m where 1=99; +select 1, max(1) from t1m where a=99; +select 1, max(1) from t1m where 1=99; + +# test with InnoDB +select min(a) from t1i; +select min(7) from t1i; +select min(7) from DUAL; +explain select min(7) from t2i join t1i; +select min(7) from t2i join t1i; + +select max(a) from t1i; +select max(7) from t1i; +select max(7) from DUAL; +explain select max(7) from t2i join t1i; +select max(7) from t2i join t1i; + +select 1, min(a) from t1i where a=99; +select 1, min(a) from t1i where 1=99; +select 1, min(1) from t1i where a=99; +select 1, min(1) from t1i where 1=99; + +select 1, max(a) from t1i where a=99; +select 1, max(a) from t1i where 1=99; +select 1, max(1) from t1i where a=99; +select 1, max(1) from t1i where 1=99; + +# mixed MyISAM/InnoDB test +explain select count(*), min(7), max(7) from t1m, t1i; +select count(*), min(7), max(7) from t1m, t1i; + +explain select count(*), min(7), max(7) from t1m, t2i; +select count(*), min(7), max(7) from t1m, t2i; + +explain select count(*), min(7), max(7) from t2m, t1i; +select count(*), min(7), max(7) from t2m, t1i; + +drop table t1m, t1i, t2m, t2i; + # End of 4.1 tests diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 6ae782db557..43468adea1a 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -552,8 +552,8 @@ void Item_sum_hybrid::cleanup() void Item_sum_hybrid::no_rows_in_result() { - Item_sum::no_rows_in_result(); was_values= FALSE; + clear(); } diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 4ab506cc4e1..3d88d85af87 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -59,8 +59,8 @@ static int maxmin_in_range(bool max_fl, Field* field, COND *cond); SYNOPSIS opt_sum_query() - tables Tables in query - all_fields All fields to be returned + tables Tables in query + all_fields All fields to be returned conds WHERE clause NOTE: @@ -80,6 +80,8 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) List_iterator_fast it(all_fields); int const_result= 1; bool recalc_const_item= 0; + longlong count= 1; + bool is_exact_count= TRUE; table_map removed_tables= 0, outer_tables= 0, used_tables= 0; table_map where_tables= 0; Item *item; @@ -88,9 +90,13 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) if (conds) where_tables= conds->used_tables(); - /* Don't replace expression on a table that is part of an outer join */ + /* + Analyze outer join dependencies, and, if possible, compute the number + of returned rows. + */ for (TABLE_LIST *tl=tables; tl ; tl= tl->next) { + /* Don't replace expression on a table that is part of an outer join */ if (tl->on_expr) { outer_tables|= tl->table->map; @@ -102,15 +108,31 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) WHERE t2.field IS NULL; */ if (tl->table->map & where_tables) - return 0; + const_result= 0; } else used_tables|= tl->table->map; + + /* + If the storage manager of 'tl' gives exact row count, compute the total + number of rows. If there are no outer table dependencies, this count + may be used as the real count. + */ + if (tl->table->file->table_flags() & HA_NOT_EXACT_COUNT) + is_exact_count= FALSE; + else + { + tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); + count*= tl->table->file->records; + } } + if (!const_result) + return 0; + /* - Iterate through item is select part and replace COUNT(), MIN() and MAX() - with constants (if possible) + Iterate through all items in the SELECT clause and replace + COUNT(), MIN() and MAX() with constants (if possible). */ while ((item= it++)) @@ -122,28 +144,14 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) case Item_sum::COUNT_FUNC: /* If the expr in count(expr) can never be null we can change this - to the number of rows in the tables + to the number of rows in the tables if this number is exact and + there are no outer joins. */ - if (!conds && !((Item_sum_count*) item)->args[0]->maybe_null) + if (!conds && !((Item_sum_count*) item)->args[0]->maybe_null && + !outer_tables && is_exact_count) { - longlong count= 1; - TABLE_LIST *table; - for (table=tables ; table ; table=table->next) - { - if (outer_tables || (table->table->file->table_flags() & - HA_NOT_EXACT_COUNT)) - { - const_result= 0; // Can't optimize left join - break; - } - tables->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); - count*= table->table->file->records; - } - if (!table) - { ((Item_sum_count*) item)->make_const(count); recalc_const_item= 1; - } } else const_result= 0; @@ -210,12 +218,27 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) } removed_tables|= table->map; } - else if (!expr->const_item()) // This is VERY seldom false + else if (!expr->const_item() || !is_exact_count) { + /* + The optimization is not applicable in both cases: + (a) 'expr' is a non-constant expression. Then we can't + replace 'expr' by a constant. + (b) 'expr' is a costant. According to ANSI, MIN/MAX must return + NULL if the query does not return any rows. Thus, if we are not + able to determine if the query returns any rows, we can't apply + the optimization and replace MIN/MAX with a constant. + */ const_result= 0; break; } - ((Item_sum_min*) item_sum)->reset(); + if (!count) + { + /* If count != 1, then we know that is_exact_count == TRUE. */ + ((Item_sum_min*) item_sum)->clear(); /* Set to NULL. */ + } + else + ((Item_sum_min*) item_sum)->reset(); /* Set to the constant value. */ ((Item_sum_min*) item_sum)->make_const(); recalc_const_item= 1; break; @@ -282,13 +305,28 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) } removed_tables|= table->map; } - else if (!expr->const_item()) // This is VERY seldom false + else if (!expr->const_item() || !is_exact_count) { + /* + The optimization is not applicable in both cases: + (a) 'expr' is a non-constant expression. Then we can't + replace 'expr' by a constant. + (b) 'expr' is a costant. According to ANSI, MIN/MAX must return + NULL if the query does not return any rows. Thus, if we are not + able to determine if the query returns any rows, we can't apply + the optimization and replace MIN/MAX with a constant. + */ const_result= 0; break; } - ((Item_sum_min*) item_sum)->reset(); - ((Item_sum_min*) item_sum)->make_const(); + if (!count) + { + /* If count != 1, then we know that is_exact_count == TRUE. */ + ((Item_sum_max*) item_sum)->clear(); /* Set to NULL. */ + } + else + ((Item_sum_max*) item_sum)->reset(); /* Set to the constant value. */ + ((Item_sum_max*) item_sum)->make_const(); recalc_const_item= 1; break; } -- cgit v1.2.1 From 24922a3092eb4d89e6b0f8c52ba7a0b29162758e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Sep 2005 14:32:19 +0500 Subject: a fix (bug #7589: Decimal types are ignored when updating data from another column). mysql-test/r/union.result: a fix (bug #7589: Decimal types are ignored when updating data from another column). removed wrong test result (see #13372) mysql-test/t/union.test: a fix (bug #7589: Decimal types are ignored when updating data from another column). removed wrong test result (see #13372) sql/field_conv.cc: a fix (bug #7589: Decimal types are ignored when updating data from another column). use memcpy() only for identical decimals. --- mysql-test/r/type_decimal.result | 9 +++++++++ mysql-test/r/union.result | 15 --------------- mysql-test/t/type_decimal.test | 10 ++++++++++ mysql-test/t/union.test | 8 -------- sql/field_conv.cc | 3 +++ 5 files changed, 22 insertions(+), 23 deletions(-) diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index a9dcabd121e..c3b2d5090ef 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -646,3 +646,12 @@ a 9999.999 0000.000 drop table t1; +create table t1(a decimal(10,5), b decimal(10,1)); +insert into t1 values(123.12345, 123.12345); +update t1 set b=a; +Warnings: +Warning 1265 Data truncated for column 'b' at row 1 +select * from t1; +a b +123.12345 123.1 +drop table t1; diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 1b5fa69d713..a3dd2c5c291 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -780,21 +780,6 @@ t1 CREATE TABLE `t1` ( `b` longblob ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1,t2; -create table t1 (d decimal(10,1)); -create table t2 (d decimal(10,9)); -insert into t1 values ("100000000.0"); -insert into t2 values ("1.23456780"); -create table t3 select * from t2 union select * from t1; -select * from t3; -d -1.234567800 -100000000.0 -show create table t3; -Table Create Table -t3 CREATE TABLE `t3` ( - `d` decimal(10,9) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -drop table t1,t2,t3; create table t1 select 1 union select -1; select * from t1; 1 diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test index a6fd99e8c9a..1f133666910 100644 --- a/mysql-test/t/type_decimal.test +++ b/mysql-test/t/type_decimal.test @@ -266,4 +266,14 @@ insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000 select * from t1; drop table t1; +# +# Bug #7589: a problem with update from column +# + +create table t1(a decimal(10,5), b decimal(10,1)); +insert into t1 values(123.12345, 123.12345); +update t1 set b=a; +select * from t1; +drop table t1; + # End of 4.1 tests diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 6acccaeafd5..6a54909536a 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -425,14 +425,6 @@ create table t1 SELECT b from t2 UNION select tx from t2; select * from t1; show create table t1; drop table t1,t2; -create table t1 (d decimal(10,1)); -create table t2 (d decimal(10,9)); -insert into t1 values ("100000000.0"); -insert into t2 values ("1.23456780"); -create table t3 select * from t2 union select * from t1; -select * from t3; -show create table t3; -drop table t1,t2,t3; create table t1 select 1 union select -1; select * from t1; show create table t1; diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 7998dd6d5f8..d61b3735c91 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -599,6 +599,9 @@ void field_conv(Field *to,Field *from) !(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) && to->real_type() != FIELD_TYPE_ENUM && to->real_type() != FIELD_TYPE_SET && + (to->real_type() != FIELD_TYPE_DECIMAL || + (to->field_length == from->field_length && + (((Field_num*) to)->dec == ((Field_num*) from)->dec))) && from->charset() == to->charset() && to->table->db_low_byte_first == from->table->db_low_byte_first) { // Identical fields -- cgit v1.2.1 From a808e97d8aa9d80ae6f310171eba34a45116518a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Sep 2005 19:58:40 +0400 Subject: Fix compiler error: C++ code in C --- myisam/myisamchk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index 1a7d2b2d9a8..2ffc491fc91 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -698,8 +698,8 @@ get_one_option(int optid, break; case OPT_STATS_METHOD: { - myisam_stats_method_str= argument; int method; + myisam_stats_method_str= argument; if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0) { fprintf(stderr, "Invalid value of stats_method: %s.\n", argument); -- cgit v1.2.1 From 6367a2c631b5a28908ecd5a8db50ce1bdcc4a667 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Sep 2005 11:45:16 +0500 Subject: a fix (#11553: gives error if aggregate user-defined function in HAVING clause). sql/sql_yacc.yy: a fix (#11553: gives error if aggregate user-defined function in HAVING clause). udf_sum_expr_list rule introduced and used for aggregate udf functions: - call inc_in_sum_expr() before udf_expr_list parsing (as in_sum_expr rule does). --- sql/sql_yacc.yy | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e29aaac8f94..a85b877838c 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -644,7 +644,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); NUM_literal %type - expr_list udf_expr_list when_list ident_list ident_list_arg + expr_list udf_expr_list udf_sum_expr_list when_list ident_list + ident_list_arg %type key_type opt_unique_or_fulltext constraint_key_type @@ -3137,21 +3138,21 @@ simple_expr: { $$= new Item_func_trim($5,$3); } | TRUNCATE_SYM '(' expr ',' expr ')' { $$= new Item_func_round($3,$5,1); } - | UDA_CHAR_SUM '(' udf_expr_list ')' + | UDA_CHAR_SUM '(' udf_sum_expr_list ')' { if ($3 != NULL) $$ = new Item_sum_udf_str($1, *$3); else $$ = new Item_sum_udf_str($1); } - | UDA_FLOAT_SUM '(' udf_expr_list ')' + | UDA_FLOAT_SUM '(' udf_sum_expr_list ')' { if ($3 != NULL) $$ = new Item_sum_udf_float($1, *$3); else $$ = new Item_sum_udf_float($1); } - | UDA_INT_SUM '(' udf_expr_list ')' + | UDA_INT_SUM '(' udf_sum_expr_list ')' { if ($3 != NULL) $$ = new Item_sum_udf_int($1, *$3); @@ -3289,6 +3290,21 @@ udf_expr_list: /* empty */ { $$= NULL; } | expr_list { $$= $1;}; +udf_sum_expr_list: + { + LEX *lex= Lex; + if (lex->current_select->inc_in_sum_expr()) + { + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } + } + udf_expr_list + { + Select->in_sum_expr--; + $$= $2; + }; + sum_expr: AVG_SYM '(' in_sum_expr ')' { $$=new Item_sum_avg($3); } -- cgit v1.2.1 From 91ed9588bf3c3dfddf9c4eee823b36e53c85a3f5 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Sep 2005 12:46:01 +0500 Subject: Fix for bug#12053 LOAD DATA INFILE ignores NO_AUTO_VALUE_ON_ZERO setting set auto_increment_field_not_null to true to preserve zero values for autoincrement fields during LOAD DATA execution if NO_AUTO_VALUE_ON_ZERO sql mode is set mysql-test/r/loaddata.result: Fix for bug#12053 LOAD DATA INFILE ignores NO_AUTO_VALUE_ON_ZERO setting test case mysql-test/t/loaddata.test: Fix for bug#12053 LOAD DATA INFILE ignores NO_AUTO_VALUE_ON_ZERO setting test case --- mysql-test/r/loaddata.result | 10 ++++++++++ mysql-test/t/loaddata.test | 27 +++++++++++++++++++++++++++ sql/sql_load.cc | 4 ++++ 3 files changed, 41 insertions(+) diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index c0baabcc507..46db14a5871 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -66,3 +66,13 @@ a b 3 row 3 0 drop table t1; +SET @OLD_SQL_MODE=@@SQL_MODE, @@SQL_MODE=NO_AUTO_VALUE_ON_ZERO; +create table t1(id integer not null auto_increment primary key); +insert into t1 values(0); +select * from t1; +id +0 +select * from t1; +id +0 +SET @@SQL_MODE=@OLD_SQL_MODE; diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index 689bdbbf92d..86fbdc62702 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -31,4 +31,31 @@ load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated select * from t1; drop table t1; + +# +# Bug #12053 LOAD DATA INFILE ignores NO_AUTO_VALUE_ON_ZERO setting +# +SET @OLD_SQL_MODE=@@SQL_MODE, @@SQL_MODE=NO_AUTO_VALUE_ON_ZERO; +create table t1(id integer not null auto_increment primary key); +insert into t1 values(0); +disable_query_log; +eval SELECT * INTO OUTFILE '$MYSQL_TEST_DIR/var/tmp/t1' from t1; +delete from t1; +eval load data infile '$MYSQL_TEST_DIR/var/tmp/t1' into table t1; +enable_query_log; +select * from t1; +--exec rm $MYSQL_TEST_DIR/var/tmp/t1 + +disable_query_log; +eval SELECT * INTO OUTFILE '$MYSQL_TEST_DIR/var/tmp/t1' +FIELDS TERMINATED BY '' OPTIONALLY ENCLOSED BY '' LINES TERMINATED BY '\r\n' +FROM t1; +delete from t1; +eval load data infile '$MYSQL_TEST_DIR/var/tmp/t1' into table t1 +FIELDS TERMINATED BY '' OPTIONALLY ENCLOSED BY '' LINES TERMINATED BY '\r\n'; +enable_query_log; +select * from t1; +--exec rm $MYSQL_TEST_DIR/var/tmp/t1 +SET @@SQL_MODE=@OLD_SQL_MODE; + # End of 4.1 tests diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 7b963c7ea31..f590038f899 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -429,6 +429,8 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List &fields, while ((sql_field= (Item_field*) it++)) { Field *field= sql_field->field; + if (field == table->next_number_field) + table->auto_increment_field_not_null= TRUE; if (pos == read_info.row_end) { thd->cuted_fields++; /* Not enough fields */ @@ -520,6 +522,8 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, length=(uint) (read_info.row_end-pos); Field *field=sql_field->field; + if (field == table->next_number_field) + table->auto_increment_field_not_null= TRUE; if (!read_info.enclosed && (enclosed_length && length == 4 && !memcmp(pos,"NULL",4)) || (length == 1 && read_info.found_null)) -- cgit v1.2.1 From 0f0f72c74f87c4cffca23704bd4a94b86b3945af Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Sep 2005 11:40:22 -0700 Subject: Fix handling of NULL values in decimal fields in FORMAT(). (Bug #13361) mysql-test/r/func_str.result: Add new results mysql-test/t/func_str.test: Add new regression test sql/item_strfunc.cc: Handle NULL decimal fields in FORMAT(). --- mysql-test/r/func_str.result | 6 ++++++ mysql-test/t/func_str.test | 10 ++++++++++ sql/item_strfunc.cc | 2 ++ 3 files changed, 18 insertions(+) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 577f943ebde..3d7d693cdce 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1011,3 +1011,9 @@ t 1000000 1 drop table t1; +create table t1 (d decimal default null); +insert into t1 values (null); +select format(d, 2) from t1; +format(d, 2) +NULL +drop table t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 4a6c98c8d7f..5f32b7b2b49 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -665,3 +665,13 @@ select rpad(i, 7, ' ') as t from t1; drop table t1; # End of 4.1 tests + +# +# Bug #13361: SELECT FORMAT(, 2) crashes +# +create table t1 (d decimal default null); +insert into t1 values (null); +select format(d, 2) from t1; +drop table t1; + +# End of 5.0 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 54c476ce176..b9ae3140393 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1733,6 +1733,8 @@ String *Item_func_format::val_str(String *str) { my_decimal dec_val, rnd_dec, *res; res= args[0]->val_decimal(&dec_val); + if ((null_value=args[0]->null_value)) + return 0; /* purecov: inspected */ my_decimal_round(E_DEC_FATAL_ERROR, res, decimals, false, &rnd_dec); my_decimal2string(E_DEC_FATAL_ERROR, &rnd_dec, 0, 0, 0, str); str_length= str->length(); -- cgit v1.2.1 From 17feba98d47e477210a98fb44c2c95cf342571f7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Sep 2005 23:03:53 +0400 Subject: Fix for bug #13407 "Remote connecting crashes server" and couple of similar problems which were introduced during work on WL#2787 "Add view definer/owner to the view definition (.frm) to check privileges on used tables and stored routines when using a VIEW." In some cases it is better to use value from Security_context::host_or_ip instead of value from Security_context::host since the latter can be NULL in certain situations (When we can't resolve hostname or we have not done this yet). mysql-test/r/skip_name_resolve.result: Added test for bug #13407 "Remote connecting crashes server". mysql-test/t/skip_name_resolve.test: Added test for bug #13407 "Remote connecting crashes server". sql/item_strfunc.cc: Item_func_user::val_str(): It is better to use value from Security_context::host_or_ip instead of value from Security_context::host in the result of USER() function since the latter can be NULL in certain situations (When we can't resolve hostname or we have not done this yet. Reverted back to old code). sql/mysqld.cc: handle_connections_shared_memory(): THD::host member has moved to the Security_context class. New THD::security_ctx member points to active security context. sql/sql_show.cc: mysqld_list_processes(): It is better to use value from Security_context::host_or_ip instead of value from Security_context::host in the processlist since the latter can be NULL in certain situations (When we can't resolve hostname or we have not done this yet. Reverted back to old code). --- mysql-test/r/skip_name_resolve.result | 7 +++++++ mysql-test/t/skip_name_resolve.test | 10 ++++++++++ sql/item_strfunc.cc | 2 +- sql/mysqld.cc | 2 +- sql/sql_show.cc | 2 +- 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/skip_name_resolve.result b/mysql-test/r/skip_name_resolve.result index d8d873699a5..a969c5c9ae0 100644 --- a/mysql-test/r/skip_name_resolve.result +++ b/mysql-test/r/skip_name_resolve.result @@ -5,3 +5,10 @@ GRANT USAGE ON *.* TO 'mysqltest_1'@'127.0.0.1/255.255.255.255' GRANT ALL PRIVILEGES ON `test`.* TO 'mysqltest_1'@'127.0.0.1/255.255.255.255' REVOKE ALL ON test.* FROM mysqltest_1@'127.0.0.1/255.255.255.255'; DROP USER mysqltest_1@'127.0.0.1/255.255.255.255'; +select user(); +user() +# +show processlist; +Id User Host db Command Time State Info +# root # test Sleep # NULL +# root # test Query # NULL show processlist diff --git a/mysql-test/t/skip_name_resolve.test b/mysql-test/t/skip_name_resolve.test index 02339ca14c5..b67869692d2 100644 --- a/mysql-test/t/skip_name_resolve.test +++ b/mysql-test/t/skip_name_resolve.test @@ -8,3 +8,13 @@ REVOKE ALL ON test.* FROM mysqltest_1@'127.0.0.1/255.255.255.255'; DROP USER mysqltest_1@'127.0.0.1/255.255.255.255'; # End of 4.1 tests + +# Bug #13407 "Remote connecting crashes server". +# Server crashed when one used USER() function in connection for which +# was impossible to obtain peer hostname. +connect (con1, 127.0.0.1, root, , test, $MASTER_MYPORT, ); +--replace_column 1 # +select user(); +--replace_column 1 # 6 # 3 # +show processlist; +connection default; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 54c476ce176..f0486246a65 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1608,7 +1608,7 @@ String *Item_func_user::val_str(String *str) else { user= thd->main_security_ctx.user; - host= thd->main_security_ctx.host; + host= thd->main_security_ctx.host_or_ip; } // For system threads (e.g. replication SQL thread) user may be empty diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 097eb9ccf17..677b68ca946 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4208,7 +4208,7 @@ pthread_handler_decl(handle_connections_shared_memory,arg) errmsg= 0; goto errorconn; } - thd->host= my_strdup(my_localhost,MYF(0)); /* Host is unknown */ + thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */ create_new_thread(thd); connect_number++; continue; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index cdbe0194303..cdd2818d897 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1205,7 +1205,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) "%s:%u", tmp_sctx->host_or_ip, tmp->peer_port); } else - thd_info->host= thd->strdup(tmp_sctx->host); + thd_info->host= thd->strdup(tmp_sctx->host_or_ip); if ((thd_info->db=tmp->db)) // Safe test thd_info->db=thd->strdup(thd_info->db); thd_info->command=(int) tmp->command; -- cgit v1.2.1 From 727f0b8a1f2fdc3f458f6b5da5ebe3cc73620403 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Sep 2005 21:24:57 +0200 Subject: Bug #13384 mysqltest, no protocol when script contains only lines with eval client/mysqltest.c: Set query_executed also for eval, that results in a query being executed and output is likely. --- client/mysqltest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/mysqltest.c b/client/mysqltest.c index f5facccee3a..1b8a0658cc7 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -3914,6 +3914,7 @@ int main(int argc, char **argv) error|= run_query(&cur_con->mysql, q, QUERY_REAP|QUERY_SEND); display_result_vertically= old_display_result_vertically; q->last_argument= q->end; + query_executed= 1; break; } case Q_QUERY: -- cgit v1.2.1 From 32de973588d71d4cb7a6decf7a83c0554de2a9a1 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Sep 2005 13:43:20 +0400 Subject: Fix for BUG#13419: In "ref" optimizer, take into account that item=Item_func_in(x,y) is not equivalent to "x=y" when item->negated == TRUE. mysql-test/r/func_in.result: Testcase for BUG#13419 mysql-test/t/func_in.test: Testcase for BUG#13419 sql/sql_select.cc: Fix for BUG#13419: * Take into account that item=Item_func_in(x,y) is not equivalent to "x=y" when item->negated == TRUE. * Removed comment that is no longer true. --- mysql-test/r/func_in.result | 9 +++++++++ mysql-test/t/func_in.test | 7 +++++++ sql/sql_select.cc | 4 ++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index 516d0a28a21..3cf2afc83d1 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -193,3 +193,12 @@ select * from t1 where a in (NULL, 'aa'); a aa drop table t1; +create table t1 (id int, key(id)); +insert into t1 values (1),(2),(3); +select count(*) from t1 where id not in (1); +count(*) +2 +select count(*) from t1 where id not in (1,2); +count(*) +1 +drop table t1; diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index aec2de7a467..2ffe5a2d5f7 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -102,4 +102,11 @@ insert into t1 values ('aa'), ('bb'); select * from t1 where a in (NULL, 'aa'); drop table t1; +# BUG#13419 +create table t1 (id int, key(id)); +insert into t1 values (1),(2),(3); +select count(*) from t1 where id not in (1); +select count(*) from t1 where id not in (1,2); +drop table t1; + # End of 4.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 59b82b53b32..0d9cab6a36b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2140,7 +2140,6 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end, field Field used in comparision eq_func True if we used =, <=> or IS NULL value Value used for comparison with field - Is NULL for BETWEEN and IN usable_tables Tables which can be used for key optimization NOTES @@ -2325,7 +2324,8 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level, add_key_field(key_fields,*and_level,cond_func, ((Item_field*)(cond_func->key_item()->real_item()))->field, cond_func->argument_count() == 2 && - cond_func->functype() == Item_func::IN_FUNC, + cond_func->functype() == Item_func::IN_FUNC && + !((Item_func_in*)cond_func)->negated, cond_func->arguments()+1, cond_func->argument_count()-1, usable_tables); break; -- cgit v1.2.1 From 72a8049b0dda6e06d893f3be64a2aced4c94eed4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Sep 2005 14:37:22 +0200 Subject: Merge from 4.1 to 5.0 mysql-test/r/loaddata.result: Add drop tablea after test case mysql-test/r/type_decimal.result: Update warnings mysql-test/r/union.result: Miss in merge mysql-test/t/loaddata.test: Add drop table after test case sql/opt_sum.cc: Add missing } sql/sql_load.cc: Manual merge --- mysql-test/r/loaddata.result | 1 + mysql-test/r/type_decimal.result | 4 +++- mysql-test/r/union.result | 15 --------------- mysql-test/t/loaddata.test | 1 + sql/opt_sum.cc | 1 + sql/sql_load.cc | 7 +++++-- 6 files changed, 11 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index e2cd89a58dc..f9d47e3533c 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -76,6 +76,7 @@ select * from t1; id 0 SET @@SQL_MODE=@OLD_SQL_MODE; +drop table t1; create table t1 (a int default 100, b int, c varchar(60)); load data infile '../../std_data/rpl_loaddata.dat' into table t1 (a, @b) set b=@b+10, c=concat("b=",@b); select * from t1; diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index 45334886823..56a2bceeccf 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -674,9 +674,11 @@ a drop table t1; create table t1(a decimal(10,5), b decimal(10,1)); insert into t1 values(123.12345, 123.12345); +Warnings: +Note 1265 Data truncated for column 'b' at row 1 update t1 set b=a; Warnings: -Warning 1265 Data truncated for column 'b' at row 1 +Note 1265 Data truncated for column 'b' at row 1 select * from t1; a b 123.12345 123.1 diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index eb129e32983..042dfb5ad8d 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -780,21 +780,6 @@ t1 CREATE TABLE `t1` ( `b` longblob ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1,t2; -create table t1 (d decimal(10,1)); -create table t2 (d decimal(10,9)); -insert into t1 values ("100000000.0"); -insert into t2 values ("1.23456780"); -create table t3 select * from t2 union select * from t1; -select * from t3; -d -1.234567800 -100000000.000000000 -show create table t3; -Table Create Table -t3 CREATE TABLE `t3` ( - `d` decimal(18,9) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -drop table t1,t2,t3; create table t1 select 1 union select -1; select * from t1; 1 diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index 54309e45c7e..cd3a8f0fd92 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -57,6 +57,7 @@ enable_query_log; select * from t1; --exec rm $MYSQL_TEST_DIR/var/tmp/t1 SET @@SQL_MODE=@OLD_SQL_MODE; +drop table t1; # End of 4.1 tests diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index d598b8e6402..2f54cce0275 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -167,6 +167,7 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) { ((Item_sum_count*) item)->make_const(count); recalc_const_item= 1; + } } else const_result= 0; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 269c19b36d0..30398375360 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -677,8 +677,6 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, pos=read_info.row_start; length=(uint) (read_info.row_end-pos); - if (field == table->next_number_field) - table->auto_increment_field_not_null= TRUE; if (!read_info.enclosed && (enclosed_length && length == 4 && !memcmp(pos,"NULL",4)) || (length == 1 && read_info.found_null)) @@ -688,6 +686,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, Field *field= ((Item_field *)item)->field; field->reset(); field->set_null(); + if (field == table->next_number_field) + table->auto_increment_field_not_null= TRUE; if (!field->maybe_null()) { if (field->type() == FIELD_TYPE_TIMESTAMP) @@ -705,9 +705,12 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, if (item->type() == Item::FIELD_ITEM) { + Field *field= ((Item_field *)item)->field; field->set_notnull(); read_info.row_end[0]=0; // Safe to change end marker + if (field == table->next_number_field) + table->auto_increment_field_not_null= TRUE; field->store((char*) pos, length, read_info.read_charset); } else -- cgit v1.2.1 From dfabe1ed3413364f824afce55d1dfc7845ce1581 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Sep 2005 16:59:19 +0400 Subject: Fixed race conditions in rpl_multi_update and rpl_multi_delete tests which caused spurious test failures. mysql-test/t/rpl_multi_delete.test: Fixed race condition in test that caused spurious test failure. To have predictable result from statements which are run on slave we need to sync master and slave explicitly. mysql-test/t/rpl_multi_update.test: Fixed race condition in test that caused spurious test failure. To have predictable result from statements which are run on slave we need to sync master and slave explicitly. --- mysql-test/t/rpl_multi_delete.test | 2 +- mysql-test/t/rpl_multi_update.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/t/rpl_multi_delete.test b/mysql-test/t/rpl_multi_delete.test index 0538d0d7bae..4a8c0ab6912 100644 --- a/mysql-test/t/rpl_multi_delete.test +++ b/mysql-test/t/rpl_multi_delete.test @@ -24,7 +24,7 @@ connection master; delete from t1; delete from t2; -connection slave; +sync_slave_with_master; # force a difference to see if master's multi-DELETE will correct it insert into t1 values(1); insert into t2 values(1); diff --git a/mysql-test/t/rpl_multi_update.test b/mysql-test/t/rpl_multi_update.test index f400e722556..f6a960434ad 100644 --- a/mysql-test/t/rpl_multi_update.test +++ b/mysql-test/t/rpl_multi_update.test @@ -33,7 +33,7 @@ delete from t2; insert into t1 values(1,1); insert into t2 values(1,1); -connection slave; +sync_slave_with_master; # force a difference to see if master's multi-UPDATE will correct it update t1 set a=2; -- cgit v1.2.1 From e4b0b0d00cfb7e668f1890bbb050a476e45a1d5d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Sep 2005 16:22:27 +0300 Subject: Fix bug #3443, better foreign key error messsages. innobase/dict/dict0dict.c: Add 'add_newline' parameter to dict_print_info_on_foreign_key_in_create_format. innobase/include/dict0dict.h: Add 'add_newline' parameter to dict_print_info_on_foreign_key_in_create_format. innobase/include/os0file.h: Add os_file_read_string. innobase/include/trx0trx.h: Add trx_set_detailed_error and trx_set_detailed_error_from_file functions and a detailed_error field to trx_struct. innobase/include/ut0mem.h: Add ut_strlcpy. innobase/os/os0file.c: Add os_file_read_string. innobase/row/row0ins.c: Add row_ins_set_detailed function and call it when needed. Adapt to changes in dict_print_info_on_foreign_key_in_create_format. innobase/trx/trx0trx.c: Add trx_set_detailed_error and trx_set_detailed_error_from_file. Clear trx->detailed_error in trx_create. innobase/ut/ut0mem.c: Add ut_strlcpy. mysql-test/r/innodb.result: Add new tests, adapt existing ones whose output was changed. mysql-test/t/innodb.test: Add new tests, adapt existing ones whose output was changed. sql/ha_innodb.cc: Add get_error_message. Clear trx->detailed_error in start_stmt and external_lock. sql/ha_innodb.h: Add get_error_message. sql/handler.cc: Add special case code in print_error for HA_ERR_ROW_IS_REFERENCED and HA_ERR_NO_REFERENCED_ROW. Change SETMSG to point to new error messages. sql/share/errmsg.txt: Add ER_ROW_IS_REFERENCED_2 and ER_NO_REFERENCED_ROW_2. --- innobase/dict/dict0dict.c | 22 ++++++++++++++++------ innobase/include/dict0dict.h | 7 ++++--- innobase/include/os0file.h | 11 +++++++++++ innobase/include/trx0trx.h | 19 +++++++++++++++++++ innobase/include/ut0mem.h | 12 ++++++++++++ innobase/os/os0file.c | 23 +++++++++++++++++++++++ innobase/row/row0ins.c | 40 ++++++++++++++++++++++++++++++++++++---- innobase/trx/trx0trx.c | 27 +++++++++++++++++++++++++++ innobase/ut/ut0mem.c | 25 +++++++++++++++++++++++++ mysql-test/r/innodb.result | 29 ++++++++++++++++++++++++++--- mysql-test/t/innodb.test | 42 +++++++++++++++++++++++++++++++++++++++--- sql/ha_innodb.cc | 16 ++++++++++++++++ sql/ha_innodb.h | 2 ++ sql/handler.cc | 20 ++++++++++++++------ sql/share/errmsg.txt | 4 ++++ 15 files changed, 274 insertions(+), 25 deletions(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 5eee57c250b..54df582d39c 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -2189,7 +2189,7 @@ dict_foreign_error_report( dict_foreign_error_report_low(file, fk->foreign_table_name); fputs(msg, file); fputs(" Constraint:\n", file); - dict_print_info_on_foreign_key_in_create_format(file, NULL, fk); + dict_print_info_on_foreign_key_in_create_format(file, NULL, fk, TRUE); if (fk->foreign_index) { fputs("\nThe index in the foreign key in table is ", file); ut_print_name(file, NULL, fk->foreign_index->name); @@ -4330,9 +4330,10 @@ CREATE TABLE. */ void dict_print_info_on_foreign_key_in_create_format( /*============================================*/ - FILE* file, /* in: file where to print */ - trx_t* trx, /* in: transaction */ - dict_foreign_t* foreign)/* in: foreign key constraint */ + FILE* file, /* in: file where to print */ + trx_t* trx, /* in: transaction */ + dict_foreign_t* foreign, /* in: foreign key constraint */ + ibool add_newline) /* in: whether to add a newline */ { const char* stripped_id; ulint i; @@ -4345,7 +4346,16 @@ dict_print_info_on_foreign_key_in_create_format( stripped_id = foreign->id; } - fputs(",\n CONSTRAINT ", file); + putc(',', file); + + if (add_newline) { + /* SHOW CREATE TABLE wants constraints each printed nicely + on its own line, while error messages want no newlines + inserted. */ + fputs("\n ", file); + } + + fputs(" CONSTRAINT ", file); ut_print_name(file, trx, stripped_id); fputs(" FOREIGN KEY (", file); @@ -4447,7 +4457,7 @@ dict_print_info_on_foreign_keys( while (foreign != NULL) { if (create_table_format) { dict_print_info_on_foreign_key_in_create_format( - file, trx, foreign); + file, trx, foreign, TRUE); } else { ulint i; fputs("; (", file); diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h index a1232acdca7..5215d51cabe 100644 --- a/innobase/include/dict0dict.h +++ b/innobase/include/dict0dict.h @@ -375,9 +375,10 @@ CREATE TABLE. */ void dict_print_info_on_foreign_key_in_create_format( /*============================================*/ - FILE* file, /* in: file where to print */ - trx_t* trx, /* in: transaction */ - dict_foreign_t* foreign);/* in: foreign key constraint */ + FILE* file, /* in: file where to print */ + trx_t* trx, /* in: transaction */ + dict_foreign_t* foreign, /* in: foreign key constraint */ + ibool add_newline); /* in: whether to add a newline */ /************************************************************************ Displays the names of the index and the table. */ void diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index adbc4afafd2..224fd59a76b 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -432,6 +432,17 @@ os_file_read( offset */ ulint n); /* in: number of bytes to read */ /*********************************************************************** +Rewind file to its start, read at most size - 1 bytes from it to str, and +NUL-terminate str. All errors are silently ignored. This function is +mostly meant to be used with temporary files. */ + +void +os_file_read_string( +/*================*/ + FILE* file, /* in: file to read from */ + char* str, /* in: buffer where to read */ + ulint size); /* in: size of buffer */ +/*********************************************************************** Requests a synchronous positioned read operation. This function does not do any error handling. In case of error it returns FALSE. */ diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index 5dbf003594f..b2081147351 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -56,6 +56,22 @@ void trx_search_latch_release_if_reserved( /*=================================*/ trx_t* trx); /* in: transaction */ +/********************************************************************** +Set detailed error message for the transaction. */ +void +trx_set_detailed_error( +/*===================*/ + trx_t* trx, /* in: transaction struct */ + char* msg); /* in: detailed error message */ +/***************************************************************** +Set detailed error message for the transaction from a file. Note that the +file is rewinded before reading from it. */ + +void +trx_set_detailed_error_from_file( +/*=============================*/ + trx_t* trx, /* in: transaction struct */ + FILE* file); /* in: file to read message from */ /******************************************************************** Retrieves the error_info field from a trx. */ @@ -649,6 +665,9 @@ struct trx_struct{ trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log records which are currently processed by a rollback operation */ + /*------------------------------*/ + char detailed_error[256]; /* detailed error message for last + error, or empty. */ }; #define TRX_MAX_N_THREADS 32 /* maximum number of concurrent diff --git a/innobase/include/ut0mem.h b/innobase/include/ut0mem.h index 74357f6bf13..8f109a64b55 100644 --- a/innobase/include/ut0mem.h +++ b/innobase/include/ut0mem.h @@ -118,6 +118,18 @@ UNIV_INLINE int ut_strcmp(const void* str1, const void* str2); +/************************************************************************** +Copies up to size - 1 characters from the NUL-terminated string src to +dst, NUL-terminating the result. Returns strlen(src), so truncation +occurred if the return value >= size. */ +ulint +ut_strlcpy( +/*=======*/ + /* out: strlen(src) */ + char* dst, /* in: destination buffer */ + const char* src, /* in: source buffer */ + ulint size); /* in: size of destination buffer */ + /************************************************************************** Compute strlen(ut_strcpyq(str, q)). */ UNIV_INLINE diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 9c87b59f018..20a3303d12d 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -2248,6 +2248,29 @@ error_handling: return(FALSE); } +/*********************************************************************** +Rewind file to its start, read at most size - 1 bytes from it to str, and +NUL-terminate str. All errors are silently ignored. This function is +mostly meant to be used with temporary files. */ + +void +os_file_read_string( +/*================*/ + FILE* file, /* in: file to read from */ + char* str, /* in: buffer where to read */ + ulint size) /* in: size of buffer */ +{ + size_t flen; + + if (size == 0) { + return; + } + + rewind(file); + flen = fread(str, 1, size - 1, file); + str[flen] = '\0'; +} + /*********************************************************************** Requests a synchronous write operation. */ diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 75d8117a73e..60d7a640f9a 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -578,6 +578,30 @@ row_ins_cascade_calc_update_vec( return(n_fields_updated); } +/************************************************************************* +Set detailed error message associated with foreign key errors for +the given transaction. */ +static +void +row_ins_set_detailed( +/*=================*/ + trx_t* trx, /* in: transaction */ + dict_foreign_t* foreign) /* in: foreign key constraint */ +{ + + FILE* tf = os_file_create_tmpfile(); + + ut_a(tf); + + ut_print_name(tf, trx, foreign->foreign_table_name); + dict_print_info_on_foreign_key_in_create_format(tf, trx, + foreign, FALSE); + + trx_set_detailed_error_from_file(trx, tf); + + fclose(tf); +} + /************************************************************************* Reports a foreign key error associated with an update or a delete of a parent table index entry. */ @@ -598,6 +622,8 @@ row_ins_foreign_report_err( FILE* ef = dict_foreign_err_file; trx_t* trx = thr_get_trx(thr); + row_ins_set_detailed(trx, foreign); + mutex_enter(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); @@ -607,7 +633,8 @@ row_ins_foreign_report_err( fputs("Foreign key constraint fails for table ", ef); ut_print_name(ef, trx, foreign->foreign_table_name); fputs(":\n", ef); - dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign); + dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, + TRUE); putc('\n', ef); fputs(errstr, ef); fputs(" in parent table, in index ", ef); @@ -648,7 +675,9 @@ row_ins_foreign_report_add_err( child table */ { FILE* ef = dict_foreign_err_file; - + + row_ins_set_detailed(trx, foreign); + mutex_enter(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); @@ -657,7 +686,8 @@ row_ins_foreign_report_add_err( fputs("Foreign key constraint fails for table ", ef); ut_print_name(ef, trx, foreign->foreign_table_name); fputs(":\n", ef); - dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign); + dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, + TRUE); fputs("\nTrying to add in child table, in index ", ef); ut_print_name(ef, trx, foreign->foreign_index->name); if (entry) { @@ -1223,6 +1253,8 @@ run_again: if (check_table == NULL || check_table->ibd_file_missing) { if (check_ref) { + row_ins_set_detailed(trx, foreign); + FILE* ef = dict_foreign_err_file; mutex_enter(&dict_foreign_err_mutex); rewind(ef); @@ -1233,7 +1265,7 @@ run_again: ut_print_name(ef, trx, foreign->foreign_table_name); fputs(":\n", ef); dict_print_info_on_foreign_key_in_create_format(ef, - trx, foreign); + trx, foreign, TRUE); fputs("\nTrying to add to index ", ef); ut_print_name(ef, trx, foreign->foreign_index->name); fputs(" tuple:\n", ef); diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 078befb81d2..10b95179a73 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -52,6 +52,32 @@ trx_start_if_not_started_noninline( trx_start_if_not_started(trx); } +/***************************************************************** +Set detailed error message for the transaction. */ + +void +trx_set_detailed_error( +/*===================*/ + trx_t* trx, /* in: transaction struct */ + char* msg) /* in: detailed error message */ +{ + ut_strlcpy(trx->detailed_error, msg, sizeof(trx->detailed_error)); +} + +/***************************************************************** +Set detailed error message for the transaction from a file. Note that the +file is rewinded before reading from it. */ + +void +trx_set_detailed_error_from_file( +/*=============================*/ + trx_t* trx, /* in: transaction struct */ + FILE* file) /* in: file to read message from */ +{ + os_file_read_string(file, trx->detailed_error, + sizeof(trx->detailed_error)); +} + /******************************************************************** Retrieves the error_info field from a trx. */ @@ -130,6 +156,7 @@ trx_create( trx->undo_no_arr = NULL; trx->error_state = DB_SUCCESS; + trx->detailed_error[0] = '\0'; trx->sess = sess; trx->que_state = TRX_QUE_RUNNING; diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c index 3e8fd79a739..c1e3ebbf35c 100644 --- a/innobase/ut/ut0mem.c +++ b/innobase/ut/ut0mem.c @@ -342,6 +342,31 @@ ut_free_all_mem(void) } } +/************************************************************************** +Copies up to size - 1 characters from the NUL-terminated string src to +dst, NUL-terminating the result. Returns strlen(src), so truncation +occurred if the return value >= size. */ + +ulint +ut_strlcpy( +/*=======*/ + /* out: strlen(src) */ + char* dst, /* in: destination buffer */ + const char* src, /* in: source buffer */ + ulint size) /* in: size of destination buffer */ +{ + ulint src_size = strlen(src); + + if (size != 0) { + ulint n = ut_min(src_size, size - 1); + + memcpy(dst, src, n); + dst[n] = '\0'; + } + + return src_size; +} + /************************************************************************** Make a quoted copy of a NUL-terminated string. Leading and trailing quotes will not be included; only embedded quotes will be escaped. diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index ffc4ab08ab4..d528e7f43d9 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1378,9 +1378,9 @@ insert into `t2`values ( 1 ) ; create table `t3` (`id` int( 11 ) not null default '0',key `id` ( `id` ) ,constraint `t2_id_fk` foreign key ( `id` ) references `t2` (`id` )) engine = innodb; insert into `t3`values ( 1 ) ; delete t3,t2,t1 from t1,t2,t3 where t1.id =1 and t2.id = t1.id and t3.id = t2.id; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)) update t1,t2,t3 set t3.id=5, t2.id=6, t1.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)) update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id; ERROR 42S22: Unknown column 't1.id' in 'where clause' drop table t3,t2,t1; @@ -1392,7 +1392,7 @@ foreign key(pid) references t1(id) on delete cascade) engine=innodb; insert into t1 values(0,0),(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6), (8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14); delete from t1 where id=0; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `t1` (`id`) ON DELETE CASCADE) delete from t1 where id=15; delete from t1 where id=0; drop table t1; @@ -2559,3 +2559,26 @@ FOREIGN KEY (b) REFERENCES test.t1(id) ) ENGINE=InnoDB; Got one of the listed errors DROP TABLE t1; +CREATE TABLE t1 +( +id INT PRIMARY KEY +) ENGINE=InnoDB; +CREATE TABLE t2 +( +v INT, +CONSTRAINT c1 FOREIGN KEY (v) REFERENCES t1(id) +) ENGINE=InnoDB; +INSERT INTO t2 VALUES(2); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`)) +INSERT INTO t1 VALUES(1); +INSERT INTO t2 VALUES(1); +DELETE FROM t1 WHERE id = 1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`)) +DROP TABLE t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +SET FOREIGN_KEY_CHECKS=0; +DROP TABLE t1; +SET FOREIGN_KEY_CHECKS=1; +INSERT INTO t2 VALUES(3); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`)) +DROP TABLE t2; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 94f33738c8c..d0ebcb9aee8 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -978,9 +978,9 @@ create table `t2` (`id` int( 11 ) not null default '0',unique key `id` ( `id` ) insert into `t2`values ( 1 ) ; create table `t3` (`id` int( 11 ) not null default '0',key `id` ( `id` ) ,constraint `t2_id_fk` foreign key ( `id` ) references `t2` (`id` )) engine = innodb; insert into `t3`values ( 1 ) ; ---error 1217 +--error 1451 delete t3,t2,t1 from t1,t2,t3 where t1.id =1 and t2.id = t1.id and t3.id = t2.id; ---error 1217 +--error 1451 update t1,t2,t3 set t3.id=5, t2.id=6, t1.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id; --error 1054 update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id; @@ -996,7 +996,7 @@ create table t1( foreign key(pid) references t1(id) on delete cascade) engine=innodb; insert into t1 values(0,0),(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6), (8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14); --- error 1217 +-- error 1451 delete from t1 where id=0; delete from t1 where id=15; delete from t1 where id=0; @@ -1482,3 +1482,39 @@ CREATE TEMPORARY TABLE t2 FOREIGN KEY (b) REFERENCES test.t1(id) ) ENGINE=InnoDB; DROP TABLE t1; + +# +# Test improved foreign key error messages (bug #3443) +# + +CREATE TABLE t1 +( + id INT PRIMARY KEY +) ENGINE=InnoDB; + +CREATE TABLE t2 +( + v INT, + CONSTRAINT c1 FOREIGN KEY (v) REFERENCES t1(id) +) ENGINE=InnoDB; + +--error 1452 +INSERT INTO t2 VALUES(2); + +INSERT INTO t1 VALUES(1); +INSERT INTO t2 VALUES(1); + +--error 1451 +DELETE FROM t1 WHERE id = 1; + +--error 1217 +DROP TABLE t1; + +SET FOREIGN_KEY_CHECKS=0; +DROP TABLE t1; +SET FOREIGN_KEY_CHECKS=1; + +--error 1452 +INSERT INTO t2 VALUES(3); + +DROP TABLE t2; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 9e10873ad63..d66996f8029 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -6065,6 +6065,8 @@ ha_innobase::start_stmt( } } + trx->detailed_error[0] = '\0'; + /* Set the MySQL flag to mark that there is an active transaction */ if (trx->active_trans == 0) { @@ -6138,6 +6140,8 @@ ha_innobase::external_lock( if (lock_type != F_UNLCK) { /* MySQL is setting a new table lock */ + trx->detailed_error[0] = '\0'; + /* Set the MySQL flag to mark that there is an active transaction */ if (trx->active_trans == 0) { @@ -6941,6 +6945,18 @@ ha_innobase::reset_auto_increment(ulonglong value) DBUG_RETURN(0); } +/* See comment in handler.cc */ +bool +ha_innobase::get_error_message(int error, String *buf) +{ + trx_t* trx = check_trx_exists(current_thd); + + buf->copy(trx->detailed_error, strlen(trx->detailed_error), + system_charset_info); + + return FALSE; +} + /*********************************************************************** Compares two 'refs'. A 'ref' is the (internal) primary key value of the row. If there is no explicitly declared non-null unique key or a primary key, then diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 1c02ac20bb4..d3c7af432a0 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -174,6 +174,8 @@ class ha_innobase: public handler void init_table_handle_for_HANDLER(); ulonglong get_auto_increment(); int reset_auto_increment(ulonglong value); + + virtual bool get_error_message(int error, String *buf); uint8 table_cache_type() { return HA_CACHE_TBL_ASKTRANSACT; } /* diff --git a/sql/handler.cc b/sql/handler.cc index 612fd0e0ca5..e0698b37e5f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -344,8 +344,8 @@ static int ha_init_errors(void) SETMSG(HA_ERR_READ_ONLY_TRANSACTION, ER(ER_READ_ONLY_TRANSACTION)); SETMSG(HA_ERR_LOCK_DEADLOCK, ER(ER_LOCK_DEADLOCK)); SETMSG(HA_ERR_CANNOT_ADD_FOREIGN, ER(ER_CANNOT_ADD_FOREIGN)); - SETMSG(HA_ERR_NO_REFERENCED_ROW, ER(ER_NO_REFERENCED_ROW)); - SETMSG(HA_ERR_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED)); + SETMSG(HA_ERR_NO_REFERENCED_ROW, ER(ER_NO_REFERENCED_ROW_2)); + SETMSG(HA_ERR_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED_2)); SETMSG(HA_ERR_NO_SAVEPOINT, "No savepoint with that name"); SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE, "Non unique key block size"); SETMSG(HA_ERR_NO_SUCH_TABLE, "No such table: '%.64s'"); @@ -1798,11 +1798,19 @@ void handler::print_error(int error, myf errflag) textno=ER_CANNOT_ADD_FOREIGN; break; case HA_ERR_ROW_IS_REFERENCED: - textno=ER_ROW_IS_REFERENCED; - break; + { + String str; + get_error_message(error, &str); + my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe()); + DBUG_VOID_RETURN; + } case HA_ERR_NO_REFERENCED_ROW: - textno=ER_NO_REFERENCED_ROW; - break; + { + String str; + get_error_message(error, &str); + my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe()); + DBUG_VOID_RETURN; + } case HA_ERR_TABLE_DEF_CHANGED: textno=ER_TABLE_DEF_CHANGED; break; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 09589c98dce..c9b717211ce 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5415,3 +5415,7 @@ ER_NO_SUCH_USER eng "There is not %-.64s@%-.64s registered" ER_FORBID_SCHEMA_CHANGE eng "Changing schema from '%-.64s' to '%-.64s' is not allowed." +ER_ROW_IS_REFERENCED_2 23000 + eng "Cannot delete or update a parent row: a foreign key constraint fails (%.192s)" +ER_NO_REFERENCED_ROW_2 23000 + eng "Cannot add or update a child row: a foreign key constraint fails (%.192s)" -- cgit v1.2.1 From 4b314fc11d2b1edfa93502206e99b4332aa1b5d9 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Sep 2005 21:28:47 +0400 Subject: Fix for yet another compilation failure on Windows which was introduced during work on WL#2787 "Add view definer/owner to the view definition (.frm) to check privileges on used tables and stored routines when using a VIEW." (aka bug #13402 "Windows VS 2003 Compiler error") sql/mysqld.cc: handle_connections_namedpipes(): THD::host member has moved to the Security_context class. New THD::security_ctx member points to active security context. --- sql/mysqld.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 677b68ca946..fc45a9d13fd 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4016,8 +4016,8 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg) delete thd; continue; } - /* host name is unknown */ - thd->host = my_strdup(my_localhost,MYF(0)); /* Host is unknown */ + /* Host is unknown */ + thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); create_new_thread(thd); } -- cgit v1.2.1 From 611dc88c160ed111cb5575fe2fbd66223caf4a4b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Sep 2005 21:36:07 +0300 Subject: row0ins.c: Fix a compilation error: Visual C++ does not seem to allow variable declaration in the middle of a program block innobase/row/row0ins.c: Fix a compilation error: Visual C++ does not seem to allow variable declaration in the middle of a program block --- innobase/row/row0ins.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 60d7a640f9a..db871a53c42 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -1253,9 +1253,10 @@ run_again: if (check_table == NULL || check_table->ibd_file_missing) { if (check_ref) { + FILE* ef = dict_foreign_err_file; + row_ins_set_detailed(trx, foreign); - FILE* ef = dict_foreign_err_file; mutex_enter(&dict_foreign_err_mutex); rewind(ef); ut_print_timestamp(ef); -- cgit v1.2.1 From 1c064d285cc18dc4a71db3a9906ef5c7aba6386b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Sep 2005 14:14:34 -0500 Subject: mysqld.cc: Fix out-of-order status variable. sql/mysqld.cc: Fix out-of-order status variable. --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 764b89812f5..605d7d0dae6 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5499,10 +5499,10 @@ struct show_var_st status_vars[]= { {"Com_show_fields", (char*) (com_stat+(uint) SQLCOM_SHOW_FIELDS),SHOW_LONG}, {"Com_show_grants", (char*) (com_stat+(uint) SQLCOM_SHOW_GRANTS),SHOW_LONG}, {"Com_show_innodb_status", (char*) (com_stat+(uint) SQLCOM_SHOW_INNODB_STATUS),SHOW_LONG}, - {"Com_show_ndb_status", (char*) (com_stat+(uint) SQLCOM_SHOW_NDBCLUSTER_STATUS),SHOW_LONG}, {"Com_show_keys", (char*) (com_stat+(uint) SQLCOM_SHOW_KEYS),SHOW_LONG}, {"Com_show_logs", (char*) (com_stat+(uint) SQLCOM_SHOW_LOGS),SHOW_LONG}, {"Com_show_master_status", (char*) (com_stat+(uint) SQLCOM_SHOW_MASTER_STAT),SHOW_LONG}, + {"Com_show_ndb_status", (char*) (com_stat+(uint) SQLCOM_SHOW_NDBCLUSTER_STATUS),SHOW_LONG}, {"Com_show_new_master", (char*) (com_stat+(uint) SQLCOM_SHOW_NEW_MASTER),SHOW_LONG}, {"Com_show_open_tables", (char*) (com_stat+(uint) SQLCOM_SHOW_OPEN_TABLES),SHOW_LONG}, {"Com_show_privileges", (char*) (com_stat+(uint) SQLCOM_SHOW_PRIVILEGES),SHOW_LONG}, -- cgit v1.2.1 From c5b8e9bbb844747f1a571cb64d660d2bb6b937d9 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Sep 2005 15:59:32 -0500 Subject: mysqld.cc: Fix out-of-order status variable. sql/mysqld.cc: Fix out-of-order status variable. --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index fc45a9d13fd..d1e4d392e26 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5827,10 +5827,10 @@ struct show_var_st status_vars[]= { {"Com_show_fields", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS}, {"Com_show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS}, {"Com_show_innodb_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_INNODB_STATUS]), SHOW_LONG_STATUS}, - {"Com_show_ndb_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NDBCLUSTER_STATUS]), SHOW_LONG_STATUS}, {"Com_show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS}, {"Com_show_logs", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_LOGS]), SHOW_LONG_STATUS}, {"Com_show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS}, + {"Com_show_ndb_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NDBCLUSTER_STATUS]), SHOW_LONG_STATUS}, {"Com_show_new_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), SHOW_LONG_STATUS}, {"Com_show_open_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS}, {"Com_show_privileges", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]), SHOW_LONG_STATUS}, -- cgit v1.2.1 From 2a4f5aacd7a6dbfbc1bf5a10a6dafb9877c44f32 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 24 Sep 2005 01:39:50 +0400 Subject: BUG#12232: Addressing docs team feedback: s/inequal/unequal/ --- myisam/mi_check.c | 2 +- myisam/myisamchk.c | 6 +++--- mysql-test/r/myisam.result | 4 ++-- sql/ha_myisam.cc | 2 +- sql/mysqld.cc | 8 ++++---- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 0c85b5234a1..7397ee4e204 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -3994,7 +3994,7 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info, ... The 'unique' array is collected in one sequential scan through the entire index. This is done in two places: in chk_index() and in sort_key_write(). - Statistics collection may consider NULLs as either equal or inequal (see + Statistics collection may consider NULLs as either equal or unequal (see SEARCH_NULL_ARE_NOT_EQUAL, MI_STATS_METHOD_*). Output is an array: diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index 2ffc491fc91..2dd05cf7e67 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -67,7 +67,7 @@ static const char *field_pack[]= "no zeros", "blob", "constant", "table-lockup", "always zero","varchar","unique-hash","?","?"}; -static const char *myisam_stats_method_str="nulls_inequal"; +static const char *myisam_stats_method_str="nulls_unequal"; static void get_options(int *argc,char * * *argv); static void print_version(void); @@ -339,7 +339,7 @@ static struct my_option my_long_options[] = REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"stats_method", OPT_STATS_METHOD, "Specifies how index statistics collection code should threat NULLs. " - "Possible values of name are \"nulls_inequal\" (default behavior for 4.1/5.0), and \"nulls_equal\" (emulate 4.0 behavior).", + "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), and \"nulls_equal\" (emulate 4.0 behavior).", (gptr*) &myisam_stats_method_str, (gptr*) &myisam_stats_method_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} @@ -471,7 +471,7 @@ static void usage(void) #include -const char *myisam_stats_method_names[] = {"nulls_inequal", "nulls_equal", +const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal", NullS}; TYPELIB myisam_stats_method_typelib= { array_elements(myisam_stats_method_names) - 1, "", diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index b3144a6903b..0a6f3ddc28b 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -611,7 +611,7 @@ test.t2 984116287 drop table t1, t2; show variables like 'myisam_stats_method'; Variable_name Value -myisam_stats_method nulls_inequal +myisam_stats_method nulls_unequal create table t1 (a int, key(a)); insert into t1 values (0),(1),(2),(3),(4); insert into t1 select NULL from t1; @@ -652,7 +652,7 @@ t1 1 a 1 a A 5 NULL NULL YES BTREE set myisam_stats_method=DEFAULT; show variables like 'myisam_stats_method'; Variable_name Value -myisam_stats_method nulls_inequal +myisam_stats_method nulls_unequal insert into t1 values (11); delete from t1 where a=11; analyze table t1; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 615cecb7a19..87529cc8713 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -39,7 +39,7 @@ const char *myisam_recover_names[] = TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"", myisam_recover_names, NULL}; -const char *myisam_stats_method_names[] = {"nulls_inequal", "nulls_equal", +const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal", NullS}; TYPELIB myisam_stats_method_typelib= { array_elements(myisam_stats_method_names) - 1, "", diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 605d7d0dae6..1b931b25647 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -369,7 +369,7 @@ char *mysqld_unix_port, *opt_mysql_tmpdir; char *my_bind_addr_str; const char **errmesg; /* Error messages */ const char *myisam_recover_options_str="OFF"; -const char *myisam_stats_method_str="nulls_inequal"; +const char *myisam_stats_method_str="nulls_unequal"; const char *sql_mode_str="OFF"; /* name of reference on left espression in rewritten IN subquery */ const char *in_left_expr_name= ""; @@ -5212,7 +5212,7 @@ The minimum value for this variable is 4096.", GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0}, {"myisam_stats_method", OPT_MYISAM_STATS_METHOD, "Specifies how MyISAM index statistics collection code should threat NULLs. " - "Possible values of name are \"nulls_inequal\" (default behavior for 4.1/5.0), and \"nulls_equal\" (emulate 4.0 behavior).", + "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), and \"nulls_equal\" (emulate 4.0 behavior).", (gptr*) &myisam_stats_method_str, (gptr*) &myisam_stats_method_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"net_buffer_length", OPT_NET_BUFFER_LENGTH, @@ -5767,7 +5767,7 @@ static void mysql_init_variables(void) query_id= thread_id= 1L; strmov(server_version, MYSQL_SERVER_VERSION); myisam_recover_options_str= sql_mode_str= "OFF"; - myisam_stats_method_str= "nulls_inequal"; + myisam_stats_method_str= "nulls_unequal"; my_bind_addr = htonl(INADDR_ANY); threads.empty(); thread_cache.empty(); @@ -5818,7 +5818,7 @@ static void mysql_init_variables(void) global_system_variables.old_passwords= 0; /* - Default behavior for 4.1 and 5.0 is to treat NULL values as inequal + Default behavior for 4.1 and 5.0 is to treat NULL values as unequal when collecting index statistics for MyISAM tables. */ global_system_variables.myisam_stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL; -- cgit v1.2.1 From f437ec9aee07473fbd0d1674c206fe42e482b41f Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 24 Sep 2005 04:11:51 +0200 Subject: mysqlbinlog.test: Windows have no 'cat' command, use < mysql.test: Windows can't handle single quotes in --exec line mysql-test/t/mysql.test: Windows can't handle single quotes in --exec line mysql-test/t/mysqlbinlog.test: Windows have no 'cat' command, use < --- mysql-test/t/mysql.test | 10 +++++----- mysql-test/t/mysqlbinlog.test | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index c1d9813ea39..0b031ea1be8 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -19,16 +19,16 @@ insert into t1 values(1); --disable_query_log # Test delimiter : supplied on the command line select "Test delimiter : from command line" as " "; ---exec $MYSQL test --delimiter=':' -e 'select * from t1:' +--exec $MYSQL test --delimiter=":" -e "select * from t1:" # Test delimiter :; supplied on the command line select "Test delimiter :; from command line" as " "; ---exec $MYSQL test --delimiter=':;' -e 'select * from t1:;' +--exec $MYSQL test --delimiter=":;" -e "select * from t1:;" # Test 'go' command (vertical output) \G select "Test 'go' command(vertical output) \G" as " "; ---exec $MYSQL test -e 'select * from t1\G' +--exec $MYSQL test -e "select * from t1\G" # Test 'go' command \g select "Test 'go' command \g" as " "; ---exec $MYSQL test -e 'select * from t1\g' +--exec $MYSQL test -e "select * from t1\g" --enable_query_log drop table t1; @@ -37,7 +37,7 @@ drop table t1; # create table t1(a int); lock tables t1 write; ---exec $MYSQL -e 'use test; select database();' +--exec $MYSQL -e "use test; select database();" unlock tables; drop table t1; diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index e5bd8c554cb..61d7d9994ba 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -102,10 +102,10 @@ select "--- --position --" as ""; select "--- reading stdin --" as ""; --enable_query_log --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec cat $MYSQL_TEST_DIR/std_data/trunc_binlog.000001 | $MYSQL_BINLOG --short-form - +--exec $MYSQL_BINLOG --short-form - < $MYSQL_TEST_DIR/std_data/trunc_binlog.000001 --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR ---exec cat $MYSQL_TEST_DIR/std_data/trunc_binlog.000001 | $MYSQL_BINLOG --short-form --position=79 - +--exec $MYSQL_BINLOG --short-form --position=79 - < $MYSQL_TEST_DIR/std_data/trunc_binlog.000001 # clean up drop table t1, t2; -- cgit v1.2.1