diff options
223 files changed, 5139 insertions, 1888 deletions
diff --git a/SSL/Makefile.am b/SSL/Makefile.am index bd3aad1e3b2..6edc6146a29 100644 --- a/SSL/Makefile.am +++ b/SSL/Makefile.am @@ -17,8 +17,8 @@ ## Process this file with automake to create Makefile.in EXTRA_DIST= NOTES cacert.pem client-cert.pem client-key.pem \ - client-req.pem run-client run-server server-cert.pem \ - server-key.pem server-req.pem + run-client run-server server-cert.pem \ + server-key.pem # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/SSL/NOTES b/SSL/NOTES index 413c724c583..a1109db8c80 100644 --- a/SSL/NOTES +++ b/SSL/NOTES @@ -40,7 +40,69 @@ openssl s_server -port 1111 -cert ../SSL/server-cert.pem -key ../SSL/server-key. +------------------------------------------- +How to generate new keys: +First we need the private key of the CA cert. Since we always throw +away the old private key for the CA, we need to generate a totally new +CA cert. Our CA cert is self signed and we will use that to sign the +server and client keys. As long as we distibute the cacert.pem they can +b oth be validated against that. + + +1) openssl genrsa 512 > cecert.pem + +2) openssl req -new -x509 -nodes -md5 -days 1000 -key cacert.pem > cacert.pem + +We now have a cacert.pem which is the public key and a cakey.pem which is the +private key of the CA. + +Steps to generate the server key. + +3) openssl req -newkey rsa:512 -md5 -days 1000 -nodes -keyout server-key.pem > server-req.pem + +4) copy ca-key.pem ca-cert.srl + +5) openssl x509 -req -in server-req.pem -days 1000 -md5 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem + + +-- adding metadata to beginning + +6) openssl x509 -in server-cert.pem -text > tmp.pem + +7) mv tmp.pem server-cert.pem + +-- And almost the same for the client. + +8) openssl req -newkey rsa:512 -md5 -days 1000 -nodes -keyout client-key.pem > client-req.pem + +9) openssl x509 -req -in client-req.pem -days 1000 -md5 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > client-cert.pem + + +-- adding metadata to beginning + +10) openssl x509 -in client-cert.pem -text > tmp.pem + +11) mv tmp.pem client-cert.pem + +The new certs are now generated. They can be verified against the cacert to test they are ok. This is actually what is done in the MySQL client and server. + +12) openssl verify -CAfile cacert.pem server-cert.pem +server-cert.pem: OK +13) openssl verify -CAfile cacert.pem client-cert.pm +client-cert.pem: OK + + +The files we add to our repository and thus distribute are +* cacert.pem - CA's public key, used to verify the client/servers pblic keys +* server-key.pem - servers private key +* server-cert.pem - servers public key +* client-key.pem - clients private key +* client-cert.pem - clients public key + + + +== OLD NOTES below == -------------------------------------------- CA stuff: diff --git a/SSL/cacert.pem b/SSL/cacert.pem index a63dae57767..b445e77d7c4 100644 --- a/SSL/cacert.pem +++ b/SSL/cacert.pem @@ -1,21 +1,17 @@ -----BEGIN CERTIFICATE----- -MIIDcTCCAtqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEBhMCU0Ux -EDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFCMSEwHwYDVQQDExhB -YnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAvBgkqhkiG9w0BCQEWImFic3RyYWN0 -Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb20wHhcNMDMwOTEyMTYxNDE2WhcNMTMw -OTA5MTYxNDE2WjCBiDELMAkGA1UEBhMCU0UxEDAOBgNVBAcTB1VwcHNhbGExETAP -BgNVBAoTCE15U1FMIEFCMSEwHwYDVQQDExhBYnN0cmFjdCBNeVNRTCBEZXZlbG9w -ZXIxMTAvBgkqhkiG9w0BCQEWImFic3RyYWN0Lm15c3FsLmRldmVsb3BlckBteXNx -bC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKrT7zp5tp5djXp+TEQs -5ZEds1XUglp/EQUQ1FMMb1Xe6gqJsQ62O+jsUe0nrUjXBrUCUy49k6mcnmQtZREj -l1pWKmzx1fgcYpxTwxaY7IKB2jik5IWprhVPmSQ+AWss43oolXMZWR+csKehqm3j -+YNZc9NsR4ydE71l0VEtJEQvAgMBAAGjgegwgeUwHQYDVR0OBBYEFIiYZdnz8osD -HWZgYSP6rXNt02iSMIG1BgNVHSMEga0wgaqAFIiYZdnz8osDHWZgYSP6rXNt02iS -oYGOpIGLMIGIMQswCQYDVQQGEwJTRTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UE -ChMITXlTUUwgQUIxITAfBgNVBAMTGEFic3RyYWN0IE15U1FMIERldmVsb3BlcjEx -MC8GCSqGSIb3DQEJARYiYWJzdHJhY3QubXlzcWwuZGV2ZWxvcGVyQG15c3FsLmNv -bYIBADAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4GBAGIL22MCIU/0sKDp -pZIhoabvNVDTfuhtene+WBCrzCzGXPZjB4+b/KAJJNvOR4zi43Kk7euu+PENs9M7 -nKpInMdhvT1RcCnUHJ3jBCvDDzXab2msqn3rxhwetWWbfE0OeEn/PoQcwiZCe7x5 -h+Zz+oUbvsEe4DjtDVgG4UH9nSSS +MIICrTCCAhagAwIBAgIJAIAO/Ybiptv1MA0GCSqGSIb3DQEBBAUAMEQxCzAJBgNV +BAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMRAwDgYDVQQHEwdVcHBzYWxhMREwDwYD +VQQKEwhNeVNRTCBBQjAeFw0wNjA1MDMwODQ4NTRaFw0wOTAxMjcwODQ4NTRaMEQx +CzAJBgNVBAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMRAwDgYDVQQHEwdVcHBzYWxh +MREwDwYDVQQKEwhNeVNRTCBBQjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA ++C46EQl1u7tQ6gb9eqc8V079gr8YmDPCEqtjO8bCIbchpjOpDITx0WZz36Sn9E72 +GPJwNip4FxLaPRIA3xNQHM5cE5U53qznlRx1Fc4O3hcWCvyCqNDl/vzPAh3pI6Bl +Ku9hfHXpp93W812smVPe9haShEXGgbEPYGzvOfVdu/MCAwEAAaOBpjCBozAdBgNV +HQ4EFgQUjIy/6OCTmqtPHBFha6/qzVk3yTcwdAYDVR0jBG0wa4AUjIy/6OCTmqtP +HBFha6/qzVk3yTehSKRGMEQxCzAJBgNVBAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxh +MRAwDgYDVQQHEwdVcHBzYWxhMREwDwYDVQQKEwhNeVNRTCBBQoIJAIAO/Ybiptv1 +MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEA8lD9zyB820Oq1aj7ZafX +De/hbdt9RIl2tzgw2K3r1KZGdXJVL0vSt5fZ51Nq9lg7OPJy3iXf+caBJEp0IJpB +uf4Gfr6zfXw+UlY6ZthRtHQHoXKcbskECjH5/ps/Uaa+dpVQ9O+Ii1rPzmgo6ztM +s+xZ46ESBt4WiHXm8kwbU9Y= -----END CERTIFICATE----- diff --git a/SSL/client-cert.pem b/SSL/client-cert.pem index 4c81162c911..fdd5c86a23f 100644 --- a/SSL/client-cert.pem +++ b/SSL/client-cert.pem @@ -1,67 +1,42 @@ Certificate: Data: - Version: 3 (0x2) + Version: 1 (0x0) Serial Number: 1 (0x1) Signature Algorithm: md5WithRSAEncryption - Issuer: C=SE, L=Uppsala, O=MySQL AB, CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com + Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB Validity - Not Before: Sep 12 16:21:19 2003 GMT - Not After : Sep 9 16:21:19 2013 GMT - Subject: C=SE, L=Uppsala, O=MySQL AB, CN=MySQL Client/Email=abstract.mysql.developer@mysql.com + Not Before: May 3 08:55:39 2006 GMT + Not After : Jan 27 08:55:39 2009 GMT + Subject: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB/emailAddress=abstract.mysql.developer@mysql.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public Key: (1024 bit) - Modulus (1024 bit): - 00:c4:03:0a:ee:e3:b1:12:fc:ee:b4:19:f4:e1:60: - 1d:e0:28:c3:96:2d:df:82:69:cd:74:7c:54:58:d0: - ae:b3:59:3f:0c:19:1c:99:10:a6:12:c9:cf:3a:64: - 05:43:8e:bf:d2:65:36:80:91:0b:65:b0:27:26:38: - c9:23:d8:36:a2:4a:f0:f7:c0:2f:68:38:70:01:27: - 29:ff:b2:c5:52:e1:6b:f1:c8:d7:c3:5c:ee:f0:37: - 6c:2a:9b:96:1a:05:9e:eb:33:a2:39:5a:77:66:62: - 27:75:1f:2f:6f:38:da:e5:9f:78:af:ca:6b:22:3f: - 57:2b:bc:a6:8f:47:d1:99:6f + RSA Public Key: (512 bit) + Modulus (512 bit): + 00:d8:db:68:28:49:84:4d:d6:0f:5c:bc:3d:9a:ab: + 70:d5:3e:f5:b5:17:ba:ef:e1:f8:87:54:30:22:1f: + 81:07:bf:f9:24:7f:8a:54:10:e9:5f:e6:99:50:04: + d4:3b:55:a9:f1:52:ad:12:2b:5a:da:5c:be:8c:3e: + 5b:9e:b0:5a:19 Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - Netscape Comment: - OpenSSL Generated Certificate - X509v3 Subject Key Identifier: - 80:81:A9:22:EB:AB:D6:CA:7E:3F:8D:BB:D1:AC:2A:F4:87:9D:13:29 - X509v3 Authority Key Identifier: - keyid:88:98:65:D9:F3:F2:8B:03:1D:66:60:61:23:FA:AD:73:6D:D3:68:92 - DirName:/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com - serial:00 - Signature Algorithm: md5WithRSAEncryption - 86:17:1c:f3:9f:10:1b:75:47:03:ca:54:ea:ef:f7:15:54:8d: - 8f:58:c9:64:7d:de:2e:bf:ea:a6:5d:72:56:c9:81:be:bb:1c: - 78:a5:91:d6:f8:77:df:9d:d2:cb:94:d9:06:61:4f:05:21:22: - 2a:ea:9e:c3:8b:4d:fe:94:c7:98:61:cd:7e:88:19:c9:92:01: - 1f:10:5b:c6:16:95:99:9b:32:01:3a:89:df:fa:0a:89:ac:fa: - b5:40:55:7a:ca:0a:bd:5d:8b:06:d8:7e:e1:44:8c:70:c8:63: - c7:77:6a:37:3d:a4:ac:57:dc:00:c1:c1:f3:72:17:5b:50:95: - ee:b7 + 07:57:bf:07:92:c2:8e:86:24:6b:0a:bf:e5:31:21:44:c3:60: + 02:a6:ac:9e:f7:db:7a:6e:fc:4f:d4:7b:54:18:80:47:d2:4a: + 63:0e:e3:f8:af:6e:58:e3:97:5a:2b:82:5d:76:20:d1:33:a0: + f5:43:a1:d1:51:f4:ca:c8:b3:1a:66:4e:0e:55:df:d2:e8:fa: + 83:18:42:f5:ec:66:40:f0:39:e8:f9:d7:cf:f6:dd:e4:7b:69: + dd:0c:92:d8:52:95:43:6f:29:3d:f0:8d:4c:dd:52:ea:6b:a0: + 39:0f:dc:59:a7:5c:37:6b:8b:05:44:b7:69:ea:a3:58:e0:4e: + ce:d6 -----BEGIN CERTIFICATE----- -MIIDkTCCAvqgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEBhMCU0Ux -EDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFCMSEwHwYDVQQDExhB -YnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAvBgkqhkiG9w0BCQEWImFic3RyYWN0 -Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb20wHhcNMDMwOTEyMTYyMTE5WhcNMTMw -OTA5MTYyMTE5WjB8MQswCQYDVQQGEwJTRTEQMA4GA1UEBxMHVXBwc2FsYTERMA8G -A1UEChMITXlTUUwgQUIxFTATBgNVBAMTDE15U1FMIENsaWVudDExMC8GCSqGSIb3 -DQEJARYiYWJzdHJhY3QubXlzcWwuZGV2ZWxvcGVyQG15c3FsLmNvbTCBnzANBgkq -hkiG9w0BAQEFAAOBjQAwgYkCgYEAxAMK7uOxEvzutBn04WAd4CjDli3fgmnNdHxU -WNCus1k/DBkcmRCmEsnPOmQFQ46/0mU2gJELZbAnJjjJI9g2okrw98AvaDhwAScp -/7LFUuFr8cjXw1zu8DdsKpuWGgWe6zOiOVp3ZmIndR8vbzja5Z94r8prIj9XK7ym -j0fRmW8CAwEAAaOCARQwggEQMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w -ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSAgaki66vWyn4/ -jbvRrCr0h50TKTCBtQYDVR0jBIGtMIGqgBSImGXZ8/KLAx1mYGEj+q1zbdNokqGB -jqSBizCBiDELMAkGA1UEBhMCU0UxEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoT -CE15U1FMIEFCMSEwHwYDVQQDExhBYnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAv -BgkqhkiG9w0BCQEWImFic3RyYWN0Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb22C -AQAwDQYJKoZIhvcNAQEEBQADgYEAhhcc858QG3VHA8pU6u/3FVSNj1jJZH3eLr/q -pl1yVsmBvrsceKWR1vh3353Sy5TZBmFPBSEiKuqew4tN/pTHmGHNfogZyZIBHxBb -xhaVmZsyATqJ3/oKiaz6tUBVesoKvV2LBth+4USMcMhjx3dqNz2krFfcAMHB83IX -W1CV7rc= +MIIB5jCCAU8CAQEwDQYJKoZIhvcNAQEEBQAwRDELMAkGA1UEBhMCU0UxEDAOBgNV +BAgTB1VwcHNhbGExEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFC +MB4XDTA2MDUwMzA4NTUzOVoXDTA5MDEyNzA4NTUzOVowdzELMAkGA1UEBhMCU0Ux +EDAOBgNVBAgTB1VwcHNhbGExEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15 +U1FMIEFCMTEwLwYJKoZIhvcNAQkBFiJhYnN0cmFjdC5teXNxbC5kZXZlbG9wZXJA +bXlzcWwuY29tMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANjbaChJhE3WD1y8PZqr +cNU+9bUXuu/h+IdUMCIfgQe/+SR/ilQQ6V/mmVAE1DtVqfFSrRIrWtpcvow+W56w +WhkCAwEAATANBgkqhkiG9w0BAQQFAAOBgQAHV78HksKOhiRrCr/lMSFEw2ACpqye +99t6bvxP1HtUGIBH0kpjDuP4r25Y45daK4JddiDRM6D1Q6HRUfTKyLMaZk4OVd/S +6PqDGEL17GZA8Dno+dfP9t3ke2ndDJLYUpVDbyk98I1M3VLqa6A5D9xZp1w3a4sF +RLdp6qNY4E7O1g== -----END CERTIFICATE----- diff --git a/SSL/client-key.pem b/SSL/client-key.pem index 58fa805e620..22f8e23ab2a 100644 --- a/SSL/client-key.pem +++ b/SSL/client-key.pem @@ -1,15 +1,9 @@ -----BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQDEAwru47ES/O60GfThYB3gKMOWLd+Cac10fFRY0K6zWT8MGRyZ -EKYSyc86ZAVDjr/SZTaAkQtlsCcmOMkj2DaiSvD3wC9oOHABJyn/ssVS4WvxyNfD -XO7wN2wqm5YaBZ7rM6I5WndmYid1Hy9vONrln3ivymsiP1crvKaPR9GZbwIDAQAB -AoGAcR7IaoGhKbIrGGl6d67+zuT3q24h9aOV3Mn7653TlNHGnvbHGFcRYPpyy+H5 -X7m8XnHm+F+80hzNGzPecP9Q12oPOyoZgeQn6bTK73OFkNcX7FAkNdyH4xVhf2aK -YOzTcQfq3gRCqXtVIg4qBShTMjJLE31R8H430Or62XmJgFECQQDjP+Kz+ecQwuTB -HADLm+GQgceIB1kLgdQoZ3deUxGvqtVImuDRViSM0F2srfJ4GfkEDhc27UI5f6ir -ZTOw4ww7AkEA3M9wCPgWNtbOXbYjaNA0IzHcjMDxQDVvJAmb3EiZlKQp4EfrESxR -ly/u08TyfwrK6q5WS7xE0ad8+95G1af4XQJBAI9+3ME20SB1YItMCniHYwSj3oHX -2fN5NKWax/Zoz+c0IV+qZMHq+kNso2oRoOUTyXk1CJWndcTnBnPMALr2c9cCQQCZ -VL7Cq6uZVx6kemcqUHH0AprZbt3YLYLI7pc5p3xmeHzPzoEQQstBhjp8+aU+zPrN -blRkcQ8E2x5yNA7SLLrNAkAhzkA+EK8hc0f9W3ncy+py0Rn0i5Ay0N3T715vkThf -CfOHE3L91dLlmYpL5xVqOpugY/2sHyxwctv97DgS6tHZ +MIIBOgIBAAJBANjbaChJhE3WD1y8PZqrcNU+9bUXuu/h+IdUMCIfgQe/+SR/ilQQ +6V/mmVAE1DtVqfFSrRIrWtpcvow+W56wWhkCAwEAAQJAK27WT6tZylUjQomZNQ89 +TBiOEbUtBbqWklQ0R8FTkH9uKV+8KYQ+k+tMkoAEGFfChB0YfofNQ2KZYWWw4yOB +WQIhAPXXDQt73aou10s+cmKM3C3WzLmIZtrvm9wNBXWDGxgTAiEA4dG4cXrZfa1M +TTbjzNU1/Jf50/M8SvZDWMPQWxJ8oqMCIH6zBpYUkHlVCsBMvsbrsc4uFfTIx7mu +I7WVQGr/1sbhAiBf4uFirjtztgZUMx5/d3k5DH80lG/hlLf8FQl/4lWx6QIhAPHw +CXfPUbUFl4r/i9Br5+exGol50qX4F3aP5Sh5EnZT -----END RSA PRIVATE KEY----- diff --git a/SSL/client-req.pem b/SSL/client-req.pem deleted file mode 100644 index b3667fb5ec6..00000000000 --- a/SSL/client-req.pem +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN CERTIFICATE REQUEST----- -MIIBvDCCASUCAQAwfDELMAkGA1UEBhMCU0UxEDAOBgNVBAcTB1VwcHNhbGExETAP -BgNVBAoTCE15U1FMIEFCMRUwEwYDVQQDEwxNeVNRTCBDbGllbnQxMTAvBgkqhkiG -9w0BCQEWImFic3RyYWN0Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb20wgZ8wDQYJ -KoZIhvcNAQEBBQADgY0AMIGJAoGBAMQDCu7jsRL87rQZ9OFgHeAow5Yt34JpzXR8 -VFjQrrNZPwwZHJkQphLJzzpkBUOOv9JlNoCRC2WwJyY4ySPYNqJK8PfAL2g4cAEn -Kf+yxVLha/HI18Nc7vA3bCqblhoFnuszojlad2ZiJ3UfL2842uWfeK/KayI/Vyu8 -po9H0ZlvAgMBAAGgADANBgkqhkiG9w0BAQQFAAOBgQAnKdk68dGJXvlj/GXwBUWN -oXWF7hq4fDmwyhmcFUqk8qZKPKFUxkcER0GLzYeUgvD2URSfaS3/YW0d7K7kXGwP -rB5edb+suaYf6mjm/w37xw/EJI9rdSKcB/3SSu8mALds7sUHDAO+MO0WkA/9d7t0 -LOsUqcDvMkKpZuYwNILwLw== ------END CERTIFICATE REQUEST----- diff --git a/SSL/server-cert.pem b/SSL/server-cert.pem index debf7026e3c..f420b4f3124 100644 --- a/SSL/server-cert.pem +++ b/SSL/server-cert.pem @@ -1,67 +1,42 @@ Certificate: Data: - Version: 3 (0x2) - Serial Number: 2 (0x2) + Version: 1 (0x0) + Serial Number: 1 (0x1) Signature Algorithm: md5WithRSAEncryption - Issuer: C=SE, L=Uppsala, O=MySQL AB, CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com + Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB Validity - Not Before: Sep 12 16:22:06 2003 GMT - Not After : Sep 9 16:22:06 2013 GMT - Subject: C=SE, L=Uppsala, O=MySQL AB, CN=MySQL Server/Email=abstract.mysql.developer@mysql.com + Not Before: May 3 08:54:13 2006 GMT + Not After : Jan 27 08:54:13 2009 GMT + Subject: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB, CN=localhost/emailAddress=abstract.mysql.developer@mysql.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public Key: (1024 bit) - Modulus (1024 bit): - 00:e9:86:7a:55:84:88:4c:be:a4:f8:92:73:30:12: - 49:0b:7a:85:87:39:34:39:0d:7d:0b:8d:18:c2:17: - 95:13:52:d2:3f:55:10:57:c8:3f:5a:f5:b2:fa:8b: - d0:67:49:cc:aa:82:fc:9f:ce:00:b4:73:f3:36:d2: - 3a:d3:c2:b0:0e:14:c3:d4:b2:21:74:a1:f0:31:81: - 60:87:98:73:5c:10:c1:b1:1a:4d:f1:f3:b0:98:3f: - f0:d7:97:9b:2b:fd:d5:21:79:b2:2f:eb:64:15:c9: - 9b:9d:fc:9e:2d:d4:f8:04:5b:ea:a9:75:4b:42:c3: - 3d:0e:4d:2a:a8:b8:ca:99:8d + RSA Public Key: (512 bit) + Modulus (512 bit): + 00:d9:fd:da:b3:fb:7c:e0:b0:03:be:97:c6:a4:36: + ac:71:af:bb:2d:e5:84:ed:f3:8f:2b:eb:11:e5:aa: + 66:ed:bf:62:6b:e3:ce:fa:80:ed:90:ff:b9:4a:39: + 20:40:b6:f2:99:bf:2f:33:b5:f2:ec:3a:90:60:1d: + 9e:94:7e:a4:1b Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - Netscape Comment: - OpenSSL Generated Certificate - X509v3 Subject Key Identifier: - 6E:E4:9B:6A:C5:EA:E4:E6:C7:EF:D7:1E:C8:63:45:60:2B:1B:D4:D4 - X509v3 Authority Key Identifier: - keyid:88:98:65:D9:F3:F2:8B:03:1D:66:60:61:23:FA:AD:73:6D:D3:68:92 - DirName:/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com - serial:00 - Signature Algorithm: md5WithRSAEncryption - 31:77:69:b9:bd:ab:29:f3:fc:5a:09:16:6f:5d:42:ea:ba:01: - 55:69:e3:75:cf:b8:d1:b7:b9:bf:da:63:85:8c:48:92:06:60: - 76:97:e0:00:78:4b:ad:da:ab:6a:90:6d:8b:03:a8:b1:e9:09: - 78:e1:29:98:56:12:60:6b:42:fe:e8:a7:c4:f8:d6:15:07:e8: - 2b:c2:d8:8a:e5:1b:2e:51:08:9b:56:e3:b3:7a:4c:3e:e5:be: - 4a:4d:f8:65:7b:a8:21:e0:ca:fe:8b:ab:d7:ec:f2:2d:f7:d0: - bf:d7:c5:23:1c:08:d8:aa:57:c7:f3:5f:ba:33:3f:78:d1:f4: - 8e:5e + de:5e:35:cd:7b:11:e6:7c:c5:7c:d6:27:4e:72:12:49:42:eb: + 6f:2c:96:f3:f4:00:78:a7:4f:9f:2d:7b:d7:30:39:af:49:4d: + df:b1:55:0d:30:be:23:6f:06:67:fd:dd:ba:98:66:36:c6:32: + b7:ed:63:fc:aa:49:cd:4f:72:98:3b:13:0e:f6:28:d7:d4:eb: + 04:6b:dc:e8:c7:04:80:92:e4:04:86:0b:ed:32:25:76:1d:a9: + 5c:a9:2c:18:2c:bd:bc:15:ed:e1:76:96:4d:bb:0d:41:44:06: + 2c:ad:45:bb:db:61:ad:17:11:cb:49:70:67:eb:c6:27:d3:91: + c8:f2 -----BEGIN CERTIFICATE----- -MIIDkTCCAvqgAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEBhMCU0Ux -EDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFCMSEwHwYDVQQDExhB -YnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAvBgkqhkiG9w0BCQEWImFic3RyYWN0 -Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb20wHhcNMDMwOTEyMTYyMjA2WhcNMTMw -OTA5MTYyMjA2WjB8MQswCQYDVQQGEwJTRTEQMA4GA1UEBxMHVXBwc2FsYTERMA8G -A1UEChMITXlTUUwgQUIxFTATBgNVBAMTDE15U1FMIFNlcnZlcjExMC8GCSqGSIb3 -DQEJARYiYWJzdHJhY3QubXlzcWwuZGV2ZWxvcGVyQG15c3FsLmNvbTCBnzANBgkq -hkiG9w0BAQEFAAOBjQAwgYkCgYEA6YZ6VYSITL6k+JJzMBJJC3qFhzk0OQ19C40Y -wheVE1LSP1UQV8g/WvWy+ovQZ0nMqoL8n84AtHPzNtI608KwDhTD1LIhdKHwMYFg -h5hzXBDBsRpN8fOwmD/w15ebK/3VIXmyL+tkFcmbnfyeLdT4BFvqqXVLQsM9Dk0q -qLjKmY0CAwEAAaOCARQwggEQMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w -ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRu5Jtqxerk5sfv -1x7IY0VgKxvU1DCBtQYDVR0jBIGtMIGqgBSImGXZ8/KLAx1mYGEj+q1zbdNokqGB -jqSBizCBiDELMAkGA1UEBhMCU0UxEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoT -CE15U1FMIEFCMSEwHwYDVQQDExhBYnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAv -BgkqhkiG9w0BCQEWImFic3RyYWN0Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb22C -AQAwDQYJKoZIhvcNAQEEBQADgYEAMXdpub2rKfP8WgkWb11C6roBVWnjdc+40be5 -v9pjhYxIkgZgdpfgAHhLrdqrapBtiwOosekJeOEpmFYSYGtC/uinxPjWFQfoK8LY -iuUbLlEIm1bjs3pMPuW+Sk34ZXuoIeDK/our1+zyLffQv9fFIxwI2KpXx/NfujM/ -eNH0jl4= +MIIB+zCCAWQCAQEwDQYJKoZIhvcNAQEEBQAwRDELMAkGA1UEBhMCU0UxEDAOBgNV +BAgTB1VwcHNhbGExEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFC +MB4XDTA2MDUwMzA4NTQxM1oXDTA5MDEyNzA4NTQxM1owgYsxCzAJBgNVBAYTAlNF +MRAwDgYDVQQIEwdVcHBzYWxhMRAwDgYDVQQHEwdVcHBzYWxhMREwDwYDVQQKEwhN +eVNRTCBBQjESMBAGA1UEAxMJbG9jYWxob3N0MTEwLwYJKoZIhvcNAQkBFiJhYnN0 +cmFjdC5teXNxbC5kZXZlbG9wZXJAbXlzcWwuY29tMFwwDQYJKoZIhvcNAQEBBQAD +SwAwSAJBANn92rP7fOCwA76XxqQ2rHGvuy3lhO3zjyvrEeWqZu2/YmvjzvqA7ZD/ +uUo5IEC28pm/LzO18uw6kGAdnpR+pBsCAwEAATANBgkqhkiG9w0BAQQFAAOBgQDe +XjXNexHmfMV81idOchJJQutvLJbz9AB4p0+fLXvXMDmvSU3fsVUNML4jbwZn/d26 +mGY2xjK37WP8qknNT3KYOxMO9ijX1OsEa9zoxwSAkuQEhgvtMiV2HalcqSwYLL28 +Fe3hdpZNuw1BRAYsrUW722GtFxHLSXBn68Yn05HI8g== -----END CERTIFICATE----- diff --git a/SSL/server-key.pem b/SSL/server-key.pem index 4292dc79929..a4842624c0c 100644 --- a/SSL/server-key.pem +++ b/SSL/server-key.pem @@ -1,15 +1,9 @@ -----BEGIN RSA PRIVATE KEY----- -MIICXgIBAAKBgQDphnpVhIhMvqT4knMwEkkLeoWHOTQ5DX0LjRjCF5UTUtI/VRBX -yD9a9bL6i9BnScyqgvyfzgC0c/M20jrTwrAOFMPUsiF0ofAxgWCHmHNcEMGxGk3x -87CYP/DXl5sr/dUhebIv62QVyZud/J4t1PgEW+qpdUtCwz0OTSqouMqZjQIDAQAB -AoGBALTq11nrjIEQbdSZ+R1z/R0kddB2U+wjdA3/6P9tr7PBxVsFdtzbKaI5mcib -iwCKX0J2qmrP+SHUdsexBZxLR4KV/Z55v9Pym99Dy+DxDA95zURyCMKRBIzlU5uN -F7USEQoltLUCsmZwNWdit0gfxSWdddkHNuI0uxTzHwuDcUlNAkEA/76zVremngNL -DlekM9NPn/8E/TXBHN1b1jdUKd7WymSJykdcm3viU98dFNZFWF8B0jiTcuBKXgpR -vTShNab/swJBAOnCGp554BLhioTyyk8qjRLt3xEsjsDljJULHVLYWcUqIkMf97GL -VLBhl6ZEI9i0WduqvgZ+Bacd0uHqIHz1Yb8CQQDm1CjqTDiGxlIoT9JVNJTZxEOs -h6gVdXY+kxHT+N3FL5luiZp8fAR7zxVgiUVtzdLG+2madfapiobcT3RyCJkhAkBI -64AaR7KasTjg2Ew7/e4cJZAcb2XozrLYG6t+GHeIhehCQEqoW+qDSy5fc4orI7eU -SuMUa2OgCjGqv7p6wKFJAkEAznmum/MbVOBpC4FsdnIGkxyFKIbh2OLY2aUb2KkK -Ouf4S8Y5Ldgszi0fnDPRaxWJzewwZKvcff2zj+mYZeAXbA== +MIIBOgIBAAJBANn92rP7fOCwA76XxqQ2rHGvuy3lhO3zjyvrEeWqZu2/YmvjzvqA +7ZD/uUo5IEC28pm/LzO18uw6kGAdnpR+pBsCAwEAAQJBAMieYdpmRoUaODf9wqh6 +ULXH/sG8i1vaXRcUHcJ50oRVfVK8/tGGvUuTDu6MeINTdahNDlYfjwOjKWVXys1w +h6ECIQDs6s7DfczK2bKCLt0zqg24mZL3rOpGmDU+TatwN1yVgwIhAOuMzdVTX39p +328+5WxJvBOFfxmSmqdDhIFpnRMvgguJAiByvKjT/km+970+1OllyvaIL0AA2OpA +tBgdC0p6tyUMdwIgKuHAWzTJbu28UolVxQgLaFZmVCZ/ZzIAfnrWsLZ2a1kCIBq/ +ywJ2cpyFlgazu8AH6KCQa0ok9s70ElaB6FEC85Al -----END RSA PRIVATE KEY----- diff --git a/SSL/server-req.pem b/SSL/server-req.pem deleted file mode 100644 index 7c3db0660ad..00000000000 --- a/SSL/server-req.pem +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN CERTIFICATE REQUEST----- -MIIBvDCCASUCAQAwfDELMAkGA1UEBhMCU0UxEDAOBgNVBAcTB1VwcHNhbGExETAP -BgNVBAoTCE15U1FMIEFCMRUwEwYDVQQDEwxNeVNRTCBTZXJ2ZXIxMTAvBgkqhkiG -9w0BCQEWImFic3RyYWN0Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb20wgZ8wDQYJ -KoZIhvcNAQEBBQADgY0AMIGJAoGBAOmGelWEiEy+pPiSczASSQt6hYc5NDkNfQuN -GMIXlRNS0j9VEFfIP1r1svqL0GdJzKqC/J/OALRz8zbSOtPCsA4Uw9SyIXSh8DGB -YIeYc1wQwbEaTfHzsJg/8NeXmyv91SF5si/rZBXJm538ni3U+ARb6ql1S0LDPQ5N -Kqi4ypmNAgMBAAGgADANBgkqhkiG9w0BAQQFAAOBgQCagJxGHBC+G5aSh3OguFn6 -z+qAC7u3B181kPBgNv20zMgLeq7YiAh3iNx4XO2+QXRGzMznFKx1tFr/mavCpgLs -p3+dCvQt5FHEFFK1D1pDeXy4146X07hOTtC9jc/jSWeVnH4ujuX5gMtZqisOyYWV -/gpw6dBtkTYlhS+y86kM/Q== ------END CERTIFICATE REQUEST----- diff --git a/client/client_priv.h b/client/client_priv.h index a9d5364df49..9e011144836 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -51,5 +51,5 @@ enum options_client #endif OPT_TRIGGERS, OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE, - OPT_TZ_UTC, OPT_AUTO_CLOSE + OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_SSL_VERIFY_SERVER_CERT }; diff --git a/client/mysql.cc b/client/mysql.cc index 69a0e37b982..900df825b25 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -448,6 +448,14 @@ int main(int argc,char *argv[]) MYF(MY_WME)); if (histfile) sprintf(histfile,"%s/.mysql_history",getenv("HOME")); + char link_name[FN_REFLEN]; + if (my_readlink(link_name, histfile, 0) == 0 && + strncmp(link_name, "/dev/null", 10) == 0) + { + /* The .mysql_history file is a symlink to /dev/null, don't use it */ + my_free(histfile, MYF(MY_ALLOW_ZERO_PTR)); + histfile= 0; + } } if (histfile) { @@ -484,7 +492,7 @@ sig_handler mysql_end(int sig) { mysql_close(&mysql); #ifdef HAVE_READLINE - if (!status.batch && !quick && !opt_html && !opt_xml) + if (!status.batch && !quick && !opt_html && !opt_xml && histfile) { /* write-history */ if (verbose) @@ -2319,7 +2327,7 @@ print_table_data(MYSQL_RES *result) uint extra_padding; /* If this column may have a null value, use "NULL" for empty. */ - if (! not_null_flag[off] && (lengths[off] == 0)) + if (! not_null_flag[off] && (cur[off] == NULL)) { buffer= "NULL"; data_length= 4; @@ -3118,6 +3126,8 @@ sql_real_connect(char *host,char *database,char *user,char *password, if (opt_use_ssl) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); #endif if (opt_protocol) mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 5b52d524f8e..57ab4e071fb 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -340,6 +340,8 @@ int main(int argc,char *argv[]) if (opt_use_ssl) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); #endif if (opt_protocol) mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index b1a931a9df1..60b54a2ed99 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -788,7 +788,8 @@ static void die(const char* fmt, ...) fprintf(stderr, "\n"); va_end(args); cleanup(); - my_end(0); + /* We cannot free DBUG, it is used in global destructors after exit(). */ + my_end(MY_DONT_FREE_DBUG); exit(1); } @@ -1460,7 +1461,8 @@ int main(int argc, char** argv) cleanup(); free_defaults(defaults_argv); my_free_open_file_info(); - my_end(0); + /* We cannot free DBUG, it is used in global destructors after exit(). */ + my_end(MY_DONT_FREE_DBUG); exit(exit_value); DBUG_RETURN(exit_value); // Keep compilers happy } diff --git a/client/mysqldump.c b/client/mysqldump.c index 78f12593f46..ee6d7b9d12b 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -905,6 +905,8 @@ static int dbConnect(char *host, char *user,char *passwd) if (opt_use_ssl) mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); #endif if (opt_protocol) mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 8694093f06b..1f9b96f91be 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -384,6 +384,8 @@ static MYSQL *db_connect(char *host, char *database, char *user, char *passwd) if (opt_use_ssl) mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); #endif if (opt_protocol) mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 504f0d9844b..d090495ff81 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -109,6 +109,8 @@ int main(int argc, char **argv) if (opt_use_ssl) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); #endif if (opt_protocol) mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); diff --git a/client/mysqltest.c b/client/mysqltest.c index ecf54e40400..fbbab4a0b3b 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -87,14 +87,6 @@ #endif #define MAX_SERVER_ARGS 64 -/* - Sometimes in a test the client starts before - the server - to solve the problem, we try again - after some sleep if connection fails the first - time -*/ -#define CON_RETRY_SLEEP 2 -#define MAX_CON_TRIES 5 #define SLAVE_POLL_INTERVAL 300000 /* 0.3 of a sec */ #define DEFAULT_DELIMITER ";" @@ -108,7 +100,7 @@ enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD, OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC, OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH, OPT_SSL_CIPHER,OPT_PS_PROTOCOL,OPT_SP_PROTOCOL,OPT_CURSOR_PROTOCOL, - OPT_VIEW_PROTOCOL}; + OPT_VIEW_PROTOCOL, OPT_SSL_VERIFY_SERVER_CERT, OPT_MAX_CONNECT_RETRIES}; /* ************************************************************************ */ /* @@ -157,6 +149,7 @@ static int record= 0, opt_sleep= -1; static char *db = 0, *pass=0; const char *user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./"; static int port = 0; +static int opt_max_connect_retries; static my_bool opt_big_test= 0, opt_compress= 0, silent= 0, verbose = 0; static my_bool tty_password= 0; static my_bool ps_protocol= 0, ps_protocol_enabled= 0; @@ -2126,9 +2119,16 @@ void init_manager() db, port, sock NOTE - This function will try to connect to the given server MAX_CON_TRIES - times and sleep CON_RETRY_SLEEP seconds between attempts before - finally giving up. This helps in situation when the client starts + + Sometimes in a test the client starts before + the server - to solve the problem, we try again + after some sleep if connection fails the first + time + + This function will try to connect to the given server + "opt_max_connect_retries" times and sleep "connection_retry_sleep" + seconds between attempts before finally giving up. + This helps in situation when the client starts before the server (which happens sometimes). It will ignore any errors during these retries. One should use connect_n_handle_errors() if he expects a connection error and wants @@ -2143,8 +2143,9 @@ int safe_connect(MYSQL* mysql, const char *host, const char *user, { int con_error= 1; my_bool reconnect= 1; + static int connection_retry_sleep= 2; /* Seconds */ int i; - for (i= 0; i < MAX_CON_TRIES; ++i) + for (i= 0; i < opt_max_connect_retries; i++) { if (mysql_real_connect(mysql, host,user, pass, db, port, sock, CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS)) @@ -2152,7 +2153,7 @@ int safe_connect(MYSQL* mysql, const char *host, const char *user, con_error= 0; break; } - sleep(CON_RETRY_SLEEP); + sleep(connection_retry_sleep); } /* TODO: change this to 0 in future versions, but the 'kill' test relies on @@ -2379,8 +2380,12 @@ int do_connect(struct st_query *q) #ifdef HAVE_OPENSSL if (opt_use_ssl || con_ssl) + { mysql_ssl_set(&next_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&next_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + &opt_ssl_verify_server_cert); + } #endif if (con_sock && !free_con_sock && *con_sock && *con_sock != FN_LIBCHAR) con_sock=fn_format(buff, con_sock, TMPDIR, "",0); @@ -2912,6 +2917,10 @@ static struct my_option my_long_options[] = {"manager-wait-timeout", OPT_MANAGER_WAIT_TIMEOUT, "Undocumented: Used for debugging.", (gptr*) &manager_wait_timeout, (gptr*) &manager_wait_timeout, 0, GET_INT, REQUIRED_ARG, 3, 0, 0, 0, 0, 0}, + {"max-connect-retries", OPT_MAX_CONNECT_RETRIES, + "Max number of connection attempts when connecting to server", + (gptr*) &opt_max_connect_retries, (gptr*) &opt_max_connect_retries, 0, + GET_INT, REQUIRED_ARG, 5, 1, 10, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Port number to use for connection.", (gptr*) &port, @@ -4605,9 +4614,14 @@ int main(int argc, char **argv) mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name); #ifdef HAVE_OPENSSL + opt_ssl_verify_server_cert= TRUE; /* Always on in mysqltest */ if (opt_use_ssl) + { mysql_ssl_set(&cur_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&cur_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + &opt_ssl_verify_server_cert); + } #endif if (!(cur_con->name = my_strdup("default", MYF(MY_WME)))) diff --git a/config/ac-macros/openssl.m4 b/config/ac-macros/openssl.m4 index a23c46eed00..af4305486a3 100644 --- a/config/ac-macros/openssl.m4 +++ b/config/ac-macros/openssl.m4 @@ -15,8 +15,9 @@ AC_DEFUN([MYSQL_FIND_OPENSSL], [ for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \ /usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib \ /usr/freeware/lib32 /usr/local/lib/ ; do - # Just to be safe, we test for ".so" anyway - if test -f $d/libssl.a || test -f $d/libssl.so || test -f $d/libssl$shrext ; then + # Test for libssl using all known library file endings + if test -f $d/libssl.a || test -f $d/libssl.so || \ + test -f $d/libssl.sl || test -f $d/libssl.dylib ; then OPENSSL_LIB=$d fi done @@ -28,8 +29,9 @@ AC_DEFUN([MYSQL_FIND_OPENSSL], [ if test -f $incs/openssl/ssl.h ; then OPENSSL_INCLUDE=-I$incs fi - # Just to be safe, we test for ".so" anyway - if test -f $libs/libssl.a || test -f $libs/libssl.so || test -f $libs/libssl$shrext ; then + # Test for libssl using all known library file endings + if test -f $d/libssl.a || test -f $d/libssl.so || \ + test -f $d/libssl.sl || test -f $d/libssl.dylib ; then OPENSSL_LIB=$libs fi ;; diff --git a/config/ac-macros/zlib.m4 b/config/ac-macros/zlib.m4 index c75bac58d7c..a01d13937ff 100644 --- a/config/ac-macros/zlib.m4 +++ b/config/ac-macros/zlib.m4 @@ -89,10 +89,11 @@ case $SYSTEM_TYPE in fi ;; *) - # Just to be safe, we test for ".so" anyway - eval shrexts=\"$shrext_cmds\" - if test \( -f "$mysql_zlib_dir/lib/libz.a" -o -f "$mysql_zlib_dir/lib/libz.so" -o \ - -f "$mysql_zlib_dir/lib/libz$shrext" \) \ + # Test for libz using all known library file endings + if test \( -f "$mysql_zlib_dir/lib/libz.a" -o \ + -f "$mysql_zlib_dir/lib/libz.so" -o \ + -f "$mysql_zlib_dir/lib/libz.sl" -o \ + -f "$mysql_zlib_dir/lib/libz.dylib" \) \ -a -f "$mysql_zlib_dir/include/zlib.h"; then ZLIB_INCLUDES="-I$mysql_zlib_dir/include" ZLIB_LIBS="-L$mysql_zlib_dir/lib -lz" diff --git a/dbug/dbug.c b/dbug/dbug.c index 91b7e7b6c4c..c991daf3617 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -271,6 +271,8 @@ static unsigned long Clock (void); static void CloseFile(FILE *fp); /* Push current debug state */ static void PushState(void); + /* Free memory associated with debug state. */ +static void FreeState (struct state *state); /* Test for tracing enabled */ static BOOLEAN DoTrace(CODE_STATE *state); /* Test to see if file is writable */ @@ -630,22 +632,7 @@ void _db_pop_ () stack = discard -> next_state; _db_fp_ = stack -> out_file; _db_pfp_ = stack -> prof_file; - if (discard -> keywords != NULL) { - FreeList (discard -> keywords); - } - if (discard -> functions != NULL) { - FreeList (discard -> functions); - } - if (discard -> processes != NULL) { - FreeList (discard -> processes); - } - if (discard -> p_functions != NULL) { - FreeList (discard -> p_functions); - } - CloseFile (discard -> out_file); - if (discard -> prof_file) - CloseFile (discard -> prof_file); - free ((char *) discard); + FreeState(discard); if (!(stack->flags & DEBUG_ON)) _db_on_=0; } @@ -1160,6 +1147,71 @@ static void PushState () stack=new_malloc; } +/* + * FUNCTION + * + * FreeState Free memory associated with a struct state. + * + * SYNOPSIS + * + * static void FreeState (state) + * struct state *state; + * + * DESCRIPTION + * + * Deallocates the memory allocated for various information in a + * state. + * + */ +static void FreeState ( +struct state *state) +{ + if (state -> keywords != NULL) { + FreeList (state -> keywords); + } + if (state -> functions != NULL) { + FreeList (state -> functions); + } + if (state -> processes != NULL) { + FreeList (state -> processes); + } + if (state -> p_functions != NULL) { + FreeList (state -> p_functions); + } + CloseFile (state -> out_file); + if (state -> prof_file) + CloseFile (state -> prof_file); + free ((char *) state); +} + + +/* + * FUNCTION + * + * _db_end_ End debugging, freeing state stack memory. + * + * SYNOPSIS + * + * static VOID _db_end_ () + * + * DESCRIPTION + * + * Ends debugging, de-allocating the memory allocated to the + * state stack. + * + * To be called at the very end of the program. + * + */ +void _db_end_ () +{ + reg1 struct state *discard; + while((discard= stack) != NULL) { + stack= discard -> next_state; + FreeState (discard); + } + _db_on_=0; +} + /* * FUNCTION diff --git a/extra/yassl/README b/extra/yassl/README index ad59fe3965e..62209723f66 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -1,4 +1,37 @@ -yaSSL Release notes, version 1.2.2 (03/27/06) +yaSSL Release notes, version 1.3.0 (04/26/06) + + + This release of yaSSL contains minor bug fixes, portability enhancements, + and libcurl support. + +See normal build instructions below under 1.0.6. + + +--To build for libcurl on Linux, Solaris, *BSD, Mac OS X, or Cygwin: + + To build for libcurl the library needs to be built without C++ globals since + the linker will be called in a C context, also libcurl configure will expect + OpenSSL library names so some symbolic links are created. + + ./configure --enable-pure-c + make + make openssl-links + + (then go to your libcurl home and tell libcurl about yaSSL) + ./configure --with-ssl=/yaSSL-HomeDir + make + + +--To build for libcurl on Win32: + + Simply add the yaSSL project as a dependency to libcurl, add + yaSSL-Home\include and yaSSL-Home\include\openssl to the include list, and + define USE_SSLEAY and USE_OPENSSL + + please email todd@yassl.com if you have any questions. + + +*******************yaSSL Release notes, version 1.2.2 (03/27/06) This release of yaSSL contains minor bug fixes and portability enhancements. diff --git a/extra/yassl/certs/ca-cert.pem b/extra/yassl/certs/ca-cert.pem new file mode 100644 index 00000000000..981dd004fc6 --- /dev/null +++ b/extra/yassl/certs/ca-cert.pem @@ -0,0 +1,53 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com + Validity + Not Before: Jan 18 20:12:32 2005 GMT + Not After : Oct 15 20:12:32 2007 GMT + Subject: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (512 bit) + Modulus (512 bit): + 00:cf:2b:14:00:b0:3c:df:6f:9e:91:40:ec:c8:f6: + 90:b2:5b:b4:70:80:a5:a4:0a:73:c7:44:f3:2a:26: + c4:2f:f1:3a:f1:c3:c4:ac:fc:c3:d2:c3:bf:f5:d7: + 6a:38:42:ad:22:ab:c8:c4:4b:4c:1d:16:af:05:34: + 7d:79:97:5e:e1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + CB:0F:1F:E9:A2:76:71:C9:E6:E8:23:A6:C1:18:B7:CC:44:CF:B9:84 + X509v3 Authority Key Identifier: + keyid:CB:0F:1F:E9:A2:76:71:C9:E6:E8:23:A6:C1:18:B7:CC:44:CF:B9:84 + DirName:/C=US/ST=Oregon/L=Portland/O=sawtooth/CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 27:f7:3d:fb:39:6f:73:a4:86:f3:a0:48:22:60:84:e9:5c:3d: + 28:36:05:16:44:98:07:87:e1:5d:b5:f3:a7:bc:33:5f:f4:29: + a9:5f:87:33:df:e6:8e:bd:e2:f3:0a:c8:00:69:ae:3d:41:47: + 03:ea:0b:4c:67:45:4b:ab:f3:39 +-----BEGIN CERTIFICATE----- +MIIC7zCCApmgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBiTELMAkGA1UEBhMCVVMx +DzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxhbmQxETAPBgNVBAoTCHNh +d3Rvb3RoMSQwIgYDVQQDExt3d3cuc2F3dG9vdGgtY29uc3VsdGluZy5jb20xHTAb +BgkqhkiG9w0BCQEWDmluZm9AeWFzc2wuY29tMB4XDTA1MDExODIwMTIzMloXDTA3 +MTAxNTIwMTIzMlowgYkxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIEwZPcmVnb24xETAP +BgNVBAcTCFBvcnRsYW5kMREwDwYDVQQKEwhzYXd0b290aDEkMCIGA1UEAxMbd3d3 +LnNhd3Rvb3RoLWNvbnN1bHRpbmcuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlh +c3NsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDPKxQAsDzfb56RQOzI9pCy +W7RwgKWkCnPHRPMqJsQv8Trxw8Ss/MPSw7/112o4Qq0iq8jES0wdFq8FNH15l17h +AgMBAAGjgekwgeYwHQYDVR0OBBYEFMsPH+midnHJ5ugjpsEYt8xEz7mEMIG2BgNV +HSMEga4wgauAFMsPH+midnHJ5ugjpsEYt8xEz7mEoYGPpIGMMIGJMQswCQYDVQQG +EwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDERMA8GA1UE +ChMIc2F3dG9vdGgxJDAiBgNVBAMTG3d3dy5zYXd0b290aC1jb25zdWx0aW5nLmNv +bTEdMBsGCSqGSIb3DQEJARYOaW5mb0B5YXNzbC5jb22CAQAwDAYDVR0TBAUwAwEB +/zANBgkqhkiG9w0BAQQFAANBACf3Pfs5b3OkhvOgSCJghOlcPSg2BRZEmAeH4V21 +86e8M1/0KalfhzPf5o694vMKyABprj1BRwPqC0xnRUur8zk= +-----END CERTIFICATE----- diff --git a/extra/yassl/certs/client-cert.der b/extra/yassl/certs/client-cert.der Binary files differnew file mode 100644 index 00000000000..b28e2753376 --- /dev/null +++ b/extra/yassl/certs/client-cert.der diff --git a/extra/yassl/certs/client-cert.pem b/extra/yassl/certs/client-cert.pem new file mode 100644 index 00000000000..81110f17252 --- /dev/null +++ b/extra/yassl/certs/client-cert.pem @@ -0,0 +1,52 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=Oregon, L=Portland, O=yaSSL, CN=www.yassl.com/emailAddress=info@yassl.com + Validity + Not Before: Jan 18 19:33:15 2005 GMT + Not After : Oct 15 19:33:15 2007 GMT + Subject: C=US, ST=Oregon, L=Portland, O=yaSSL, CN=www.yassl.com/emailAddress=info@yassl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (512 bit) + Modulus (512 bit): + 00:cd:1f:78:47:f8:b8:d6:08:bf:bd:7c:23:61:86: + 36:28:ac:ee:3c:a8:9a:94:e6:d5:26:e8:71:50:b2: + 26:8b:1c:1e:3f:75:b2:d3:b3:67:95:0c:fd:76:28: + 65:d5:ce:12:82:9e:06:00:a2:09:dd:ce:3a:26:dd: + 46:2a:a0:45:71 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + AE:25:5E:FA:4D:A3:5B:2B:87:DE:F1:2A:F5:42:C0:FF:CE:B5:B4:AD + X509v3 Authority Key Identifier: + keyid:AE:25:5E:FA:4D:A3:5B:2B:87:DE:F1:2A:F5:42:C0:FF:CE:B5:B4:AD + DirName:/C=US/ST=Oregon/L=Portland/O=yaSSL/CN=www.yassl.com/emailAddress=info@yassl.com + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + c5:82:26:0c:1f:61:01:14:b0:ce:18:99:64:91:0e:f1:f8:90: + 3e:a3:0e:be:38:7c:97:ba:05:c9:2a:dc:dd:62:2d:12:61:79: + 7a:86:b1:97:5d:1e:e8:f7:e8:32:34:f7:8f:b1:08:3d:13:71: + a6:3c:15:91:85:12:35:6e:78:87 +-----BEGIN CERTIFICATE----- +MIICtzCCAmGgAwIBAgIBADANBgkqhkiG9w0BAQQFADB4MQswCQYDVQQGEwJVUzEP +MA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDEOMAwGA1UEChMFeWFT +U0wxFjAUBgNVBAMTDXd3dy55YXNzbC5jb20xHTAbBgkqhkiG9w0BCQEWDmluZm9A +eWFzc2wuY29tMB4XDTA1MDExODE5MzMxNVoXDTA3MTAxNTE5MzMxNVoweDELMAkG +A1UEBhMCVVMxDzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxhbmQxDjAM +BgNVBAoTBXlhU1NMMRYwFAYDVQQDEw13d3cueWFzc2wuY29tMR0wGwYJKoZIhvcN +AQkBFg5pbmZvQHlhc3NsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDNH3hH ++LjWCL+9fCNhhjYorO48qJqU5tUm6HFQsiaLHB4/dbLTs2eVDP12KGXVzhKCngYA +ogndzjom3UYqoEVxAgMBAAGjgdUwgdIwHQYDVR0OBBYEFK4lXvpNo1srh97xKvVC +wP/OtbStMIGiBgNVHSMEgZowgZeAFK4lXvpNo1srh97xKvVCwP/OtbStoXykejB4 +MQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFu +ZDEOMAwGA1UEChMFeWFTU0wxFjAUBgNVBAMTDXd3dy55YXNzbC5jb20xHTAbBgkq +hkiG9w0BCQEWDmluZm9AeWFzc2wuY29tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQEEBQADQQDFgiYMH2EBFLDOGJlkkQ7x+JA+ow6+OHyXugXJKtzdYi0SYXl6 +hrGXXR7o9+gyNPePsQg9E3GmPBWRhRI1bniH +-----END CERTIFICATE----- diff --git a/extra/yassl/certs/client-key.der b/extra/yassl/certs/client-key.der Binary files differnew file mode 100644 index 00000000000..6e8b432a07c --- /dev/null +++ b/extra/yassl/certs/client-key.der diff --git a/extra/yassl/certs/client-key.pem b/extra/yassl/certs/client-key.pem new file mode 100644 index 00000000000..6898b2796fa --- /dev/null +++ b/extra/yassl/certs/client-key.pem @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBOgIBAAJBAM0feEf4uNYIv718I2GGNiis7jyompTm1SbocVCyJoscHj91stOz +Z5UM/XYoZdXOEoKeBgCiCd3OOibdRiqgRXECAwEAAQJAXwa6OVVvg7Bv63+MAI0l +n/hlMfLGEj9R9gFvJXwywPSEQhijOZmedpHALufFPNHtwba9dmbqMkBAw9JDaAgg +QQIhAO+mBaSmoG5AYVKYQZiASe/2wMZjaQSN+zFLyF97OX8ZAiEA2x5iRmXUkbOT +8Td/vx8R9mq9W5CJu+cN+SWGwTYhPBkCIGZFM6NQeKaUUvQshdHO7b66Twpa4jZP +YSNoc9pLe/4BAiB+jIvBkKo2A/rbg2waG32qTXdTXKTPiuA9Fnk/OV30cQIhANuA +uMdo+T+rYcNGJ1hCYKDe9JWBpNfSQ+H/A7sWuW8L +-----END RSA PRIVATE KEY----- diff --git a/extra/yassl/certs/dh1024.dat b/extra/yassl/certs/dh1024.dat new file mode 100644 index 00000000000..86a95518278 --- /dev/null +++ b/extra/yassl/certs/dh1024.dat @@ -0,0 +1 @@ +30818702818100DA9A18547FF03B385CC16508C173A7EF4EB61CB40EF8FEF3B31F145051676166BCDC3FE6B799FC394D08C26385F9413F896E09117E46209D6923602683CEA100924A6EE695281775C619DAA94EA8CB3691B4275B0183F1D39639EBC92995FE645D6C1BC28D409E585549BBD2C5DCDD6C208B04EADD8B7A6D997F72CBAD88390F020102
\ No newline at end of file diff --git a/extra/yassl/certs/dsa-cert.pem b/extra/yassl/certs/dsa-cert.pem new file mode 100644 index 00000000000..ecca18dae82 --- /dev/null +++ b/extra/yassl/certs/dsa-cert.pem @@ -0,0 +1,68 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: dsaWithSHA1 + Issuer: C=US, ST=Oregon, L=Portland, O=yaSSL DSA, CN=yaSSL DSA/emailAddress=info@yassl.com + Validity + Not Before: Jan 23 22:54:51 2005 GMT + Not After : Oct 20 22:54:51 2007 GMT + Subject: C=US, ST=Oregon, L=Portland, O=yaSSL DSA, CN=yaSSL DSA/emailAddress=info@yassl.com + Subject Public Key Info: + Public Key Algorithm: dsaEncryption + DSA Public Key: + pub: + 04:84:a0:26:31:72:0c:e8:4f:5d:53:17:62:b1:80: + ca:c0:16:5f:c3:1e:ea:c5:d9:98:38:f9:be:56:53: + 47:68:ce:08:22:57:1c:bb:0d:77:91:cf:5b:36:ed: + f3:24:82:90:8a:cd:90:7c:db:77:f9:17:2d:73:73: + ef:bb:b9:82 + P: + 00:99:29:69:80:c9:3c:98:68:45:a9:82:fe:67:eb: + 95:88:c5:b4:0c:d6:26:45:95:19:2c:a0:20:5b:7e: + df:69:e9:dc:c3:0f:f3:61:0a:25:9b:f2:21:01:6a: + cd:aa:8c:37:e7:ca:66:db:56:f4:0f:7d:7a:d1:18: + b9:42:fd:1b:11 + Q: + 00:ad:25:29:ab:0a:9f:09:1c:c1:ad:03:20:76:7f: + a6:b7:dd:4d:03:09 + G: + 12:88:99:da:e7:d0:0b:93:9b:e6:ee:3c:21:7f:9c: + b3:b4:8d:a5:8c:e2:37:80:3f:17:d1:81:4f:bd:f0: + 71:b6:32:08:54:dd:bf:01:e2:b3:77:06:64:75:8a: + 04:d6:79:39:b1:02:03:03:c6:06:74:e5:90:05:0a: + 10:46:19:31 + X509v3 extensions: + X509v3 Subject Key Identifier: + BE:F9:8C:5D:D6:1C:B4:EE:81:DD:36:56:0A:21:E4:61:44:73:E9:E2 + X509v3 Authority Key Identifier: + keyid:BE:F9:8C:5D:D6:1C:B4:EE:81:DD:36:56:0A:21:E4:61:44:73:E9:E2 + DirName:/C=US/ST=Oregon/L=Portland/O=yaSSL DSA/CN=yaSSL DSA/emailAddress=info@yassl.com + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: dsaWithSHA1 + 30:2b:02:14:74:46:9f:91:7b:24:17:3b:ee:0f:10:e3:76:62: + f4:dc:81:e6:fd:fe:02:13:08:f4:87:0a:ab:ba:9c:de:3a:69: + 72:59:b8:ec:e9:57:f4:bf:37 +-----BEGIN CERTIFICATE----- +MIIDMTCCAvKgAwIBAgIBADAJBgcqhkjOOAQDMHgxCzAJBgNVBAYTAlVTMQ8wDQYD +VQQIEwZPcmVnb24xETAPBgNVBAcTCFBvcnRsYW5kMRIwEAYDVQQKEwl5YVNTTCBE +U0ExEjAQBgNVBAMTCXlhU1NMIERTQTEdMBsGCSqGSIb3DQEJARYOaW5mb0B5YXNz +bC5jb20wHhcNMDUwMTIzMjI1NDUxWhcNMDcxMDIwMjI1NDUxWjB4MQswCQYDVQQG +EwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDESMBAGA1UE +ChMJeWFTU0wgRFNBMRIwEAYDVQQDEwl5YVNTTCBEU0ExHTAbBgkqhkiG9w0BCQEW +DmluZm9AeWFzc2wuY29tMIHwMIGoBgcqhkjOOAQBMIGcAkEAmSlpgMk8mGhFqYL+ +Z+uViMW0DNYmRZUZLKAgW37faencww/zYQolm/IhAWrNqow358pm21b0D3160Ri5 +Qv0bEQIVAK0lKasKnwkcwa0DIHZ/prfdTQMJAkASiJna59ALk5vm7jwhf5yztI2l +jOI3gD8X0YFPvfBxtjIIVN2/AeKzdwZkdYoE1nk5sQIDA8YGdOWQBQoQRhkxA0MA +AkAEhKAmMXIM6E9dUxdisYDKwBZfwx7qxdmYOPm+VlNHaM4IIlccuw13kc9bNu3z +JIKQis2QfNt3+Rctc3Pvu7mCo4HVMIHSMB0GA1UdDgQWBBS++Yxd1hy07oHdNlYK +IeRhRHPp4jCBogYDVR0jBIGaMIGXgBS++Yxd1hy07oHdNlYKIeRhRHPp4qF8pHow +eDELMAkGA1UEBhMCVVMxDzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxh +bmQxEjAQBgNVBAoTCXlhU1NMIERTQTESMBAGA1UEAxMJeWFTU0wgRFNBMR0wGwYJ +KoZIhvcNAQkBFg5pbmZvQHlhc3NsLmNvbYIBADAMBgNVHRMEBTADAQH/MAkGByqG +SM44BAMDLgAwKwIUdEafkXskFzvuDxDjdmL03IHm/f4CEwj0hwqrupzeOmlyWbjs +6Vf0vzc= +-----END CERTIFICATE----- diff --git a/extra/yassl/certs/dsa512.der b/extra/yassl/certs/dsa512.der Binary files differnew file mode 100644 index 00000000000..fe79ccb612b --- /dev/null +++ b/extra/yassl/certs/dsa512.der diff --git a/extra/yassl/certs/dsa512.pem b/extra/yassl/certs/dsa512.pem new file mode 100644 index 00000000000..04a3dd94a77 --- /dev/null +++ b/extra/yassl/certs/dsa512.pem @@ -0,0 +1,8 @@ +-----BEGIN DSA PRIVATE KEY----- +MIH3AgEAAkEAmSlpgMk8mGhFqYL+Z+uViMW0DNYmRZUZLKAgW37faencww/zYQol +m/IhAWrNqow358pm21b0D3160Ri5Qv0bEQIVAK0lKasKnwkcwa0DIHZ/prfdTQMJ +AkASiJna59ALk5vm7jwhf5yztI2ljOI3gD8X0YFPvfBxtjIIVN2/AeKzdwZkdYoE +1nk5sQIDA8YGdOWQBQoQRhkxAkAEhKAmMXIM6E9dUxdisYDKwBZfwx7qxdmYOPm+ +VlNHaM4IIlccuw13kc9bNu3zJIKQis2QfNt3+Rctc3Pvu7mCAhQjg+e+aqykxwwc +E2V27tjDFY02uA== +-----END DSA PRIVATE KEY----- diff --git a/extra/yassl/certs/server-cert.pem b/extra/yassl/certs/server-cert.pem new file mode 100644 index 00000000000..403dabdf5fa --- /dev/null +++ b/extra/yassl/certs/server-cert.pem @@ -0,0 +1,38 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com + Validity + Not Before: Jan 18 20:50:59 2005 GMT + Not After : Oct 15 20:50:59 2007 GMT + Subject: C=US, ST=Oregon, L=Portland, O=taoSoftDev, CN=www.taosoftdev.com/emailAddress=info@yassl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (512 bit) + Modulus (512 bit): + 00:a4:68:bb:bc:b7:27:5f:3c:f5:78:c6:1a:af:b9: + 95:fc:7e:61:1f:a8:81:0a:ca:43:88:9a:03:e0:d0: + a6:79:70:16:34:b9:7c:75:54:ca:70:19:66:38:be: + 6e:28:7e:a5:ff:6b:3c:83:2f:39:42:c3:15:f3:bd: + f2:25:93:22:e7 + Exponent: 65537 (0x10001) + Signature Algorithm: md5WithRSAEncryption + 08:36:07:8c:3a:7f:f9:91:0a:82:d1:6a:c1:34:be:bc:2d:b2: + 20:98:dc:45:50:53:9c:66:e6:26:71:bd:fa:d2:b4:91:d3:53: + c0:20:05:c0:b6:84:9a:5f:3f:61:75:f5:fd:c6:ec:e2:f6:9f: + a2:13:17:a9:b7:83:60:cc:cb:eb +-----BEGIN CERTIFICATE----- +MIIB9zCCAaECAQEwDQYJKoZIhvcNAQEEBQAwgYkxCzAJBgNVBAYTAlVTMQ8wDQYD +VQQIEwZPcmVnb24xETAPBgNVBAcTCFBvcnRsYW5kMREwDwYDVQQKEwhzYXd0b290 +aDEkMCIGA1UEAxMbd3d3LnNhd3Rvb3RoLWNvbnN1bHRpbmcuY29tMR0wGwYJKoZI +hvcNAQkBFg5pbmZvQHlhc3NsLmNvbTAeFw0wNTAxMTgyMDUwNTlaFw0wNzEwMTUy +MDUwNTlaMIGCMQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQH +EwhQb3J0bGFuZDETMBEGA1UEChMKdGFvU29mdERldjEbMBkGA1UEAxMSd3d3LnRh +b3NvZnRkZXYuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlhc3NsLmNvbTBcMA0G +CSqGSIb3DQEBAQUAA0sAMEgCQQCkaLu8tydfPPV4xhqvuZX8fmEfqIEKykOImgPg +0KZ5cBY0uXx1VMpwGWY4vm4ofqX/azyDLzlCwxXzvfIlkyLnAgMBAAEwDQYJKoZI +hvcNAQEEBQADQQAINgeMOn/5kQqC0WrBNL68LbIgmNxFUFOcZuYmcb360rSR01PA +IAXAtoSaXz9hdfX9xuzi9p+iExept4NgzMvr +-----END CERTIFICATE----- diff --git a/extra/yassl/certs/server-key.pem b/extra/yassl/certs/server-key.pem new file mode 100644 index 00000000000..d6055c4cfd8 --- /dev/null +++ b/extra/yassl/certs/server-key.pem @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBOQIBAAJBAKRou7y3J1889XjGGq+5lfx+YR+ogQrKQ4iaA+DQpnlwFjS5fHVU +ynAZZji+bih+pf9rPIMvOULDFfO98iWTIucCAwEAAQJABLVvMw931DV1vljGKORC +1HF2LKbx0zJJzt7CX6z6J54vcE79K3NYXdU6o7/j1WTtfD47tFG+4ljGvSYPmrCI +2QIhANfiY6is6JUJGGgeMxyWeQRPXfaE9Yrk6OhxHhpYf5CTAiEAwvWraeLPy/NE +B+0w80mh8tCv2tpuKaYMOG53XpYX3N0CIDy/Bj3rUZLGOWjqvoUXzjupPY5lgVYw +7Vyin87YAiUjAiAgM8X5em5KSMc+6+2+8bWfTtsNMjEqDfRMyepLpE0SvQIgTSYL +WWfcZoRUPDM9GEuQ40nifVNjobzvjTW4aYyHCEI= +-----END RSA PRIVATE KEY----- diff --git a/extra/yassl/certs/taoCert.txt b/extra/yassl/certs/taoCert.txt new file mode 100644 index 00000000000..585293e4f2b --- /dev/null +++ b/extra/yassl/certs/taoCert.txt @@ -0,0 +1,50 @@ + +***** Create a self signed cert ************ + +1) openssl genrsa 512 > client-key.pem + +2) openssl req -new -x509 -nodes -md5 -days 1000 -key client-key.pem > client-cert.pem + +-- adding metadata to beginning + +3) openssl x509 -in client-cert.pem -text > tmp.pem + +4) mv tmp.pem client-cert.pem + + +***** Create a CA, signing authority ********** + +same as self signed, use ca prefix instead of client + + +***** Create a cert signed by CA ************** + +1) openssl req -newkey rsa:512 -md5 -days 1000 -nodes -keyout server-key.pem > server-req.pem + +2) copy ca-key.pem ca-cert.srl (why ????) + +3) openssl x509 -req -in server-req.pem -days 1000 -md5 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem + + + +***** To create a dsa cert ******************** + +1) openssl dsaparam 512 > dsa512.param # creates group params + +2) openssl gendsa dsa512.param > dsa512.pem # creates private key + +3) openssl req -new -x509 -nodes -days 1000 -key dsa512.pem > dsa-cert.pem + + + + +***** To convert from PEM to DER ************** + +a) openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER + +to convert rsa private PEM to DER : + +b) openssl rsa -in key.pem -outform DER -out key.der + + + diff --git a/extra/yassl/examples/client/client.cpp b/extra/yassl/examples/client/client.cpp index 704a8e76637..94bf753210b 100644 --- a/extra/yassl/examples/client/client.cpp +++ b/extra/yassl/examples/client/client.cpp @@ -33,10 +33,10 @@ void client_test(void* args) const char* cipher = 0; int index = 0; char list[1024]; - strcpy(list, "cipherlist"); + strncpy(list, "cipherlist", 11); while ( (cipher = SSL_get_cipher_list(ssl, index++)) ) { - strcat(list, ":"); - strcat(list, cipher); + strncat(list, ":", 2); + strncat(list, cipher, strlen(cipher) + 1); } printf("%s\n", list); printf("Using Cipher Suite %s\n", SSL_get_cipher(ssl)); @@ -89,6 +89,8 @@ void client_test(void* args) args.argv = argv; client_test(&args); + yaSSL_CleanUp(); + return args.return_code; } diff --git a/extra/yassl/examples/echoclient/echoclient.cpp b/extra/yassl/examples/echoclient/echoclient.cpp index ca557cca8af..fd3f7dd48a3 100644 --- a/extra/yassl/examples/echoclient/echoclient.cpp +++ b/extra/yassl/examples/echoclient/echoclient.cpp @@ -82,6 +82,7 @@ void echoclient_test(void* args) args.argv = argv; echoclient_test(&args); + yaSSL_CleanUp(); return args.return_code; } diff --git a/extra/yassl/examples/echoserver/echoserver.cpp b/extra/yassl/examples/echoserver/echoserver.cpp index 14a37a7e175..3243cc21a7c 100644 --- a/extra/yassl/examples/echoserver/echoserver.cpp +++ b/extra/yassl/examples/echoserver/echoserver.cpp @@ -15,6 +15,8 @@ args.argv = argv; echoserver_test(&args); + yaSSL_CleanUp(); + return args.return_code; } diff --git a/extra/yassl/examples/server/server.cpp b/extra/yassl/examples/server/server.cpp index 4d3f121cf2c..73cff19e371 100644 --- a/extra/yassl/examples/server/server.cpp +++ b/extra/yassl/examples/server/server.cpp @@ -67,6 +67,8 @@ THREAD_RETURN YASSL_API server_test(void* args) args.argv = argv; server_test(&args); + yaSSL_CleanUp(); + return args.return_code; } diff --git a/extra/yassl/include/openssl/err.h b/extra/yassl/include/openssl/err.h index 054d0940509..45ac1ca2469 100644 --- a/extra/yassl/include/openssl/err.h +++ b/extra/yassl/include/openssl/err.h @@ -1,6 +1,6 @@ /* err.h for openssl */ -#ifndef ysSSL_err_h__ +#ifndef yaSSL_err_h__ #define yaSSL_err_h__ diff --git a/extra/yassl/include/openssl/md4.h b/extra/yassl/include/openssl/md4.h new file mode 100644 index 00000000000..2e99f977fca --- /dev/null +++ b/extra/yassl/include/openssl/md4.h @@ -0,0 +1 @@ +/* md4.h for libcurl */ diff --git a/extra/yassl/include/openssl/md5.h b/extra/yassl/include/openssl/md5.h index a1025b92782..dfaf9799c44 100644 --- a/extra/yassl/include/openssl/md5.h +++ b/extra/yassl/include/openssl/md5.h @@ -1 +1,4 @@ /* md5.h for openssl */ + +#include "ssl.h" /* in there for now */ + diff --git a/extra/yassl/include/openssl/pem.h b/extra/yassl/include/openssl/pem.h new file mode 100644 index 00000000000..b4c63d56a4d --- /dev/null +++ b/extra/yassl/include/openssl/pem.h @@ -0,0 +1 @@ +/* pem.h for libcurl */ diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index b6840d006df..a7eca9138a2 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -29,8 +29,22 @@ #define yaSSL_openssl_h__ #include <stdio.h> /* ERR_print fp */ +#include "opensslv.h" /* for version number */ #include "rsa.h" +#if defined(__cplusplus) +extern "C" { +#endif + + void yaSSL_CleanUp(); /* call once at end of application use to + free static singleton memory holders, + not a leak per se, but helpful when + looking for them */ + +#if defined(__cplusplus) +} // extern +#endif + #if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE) namespace yaSSL { extern "C" { @@ -102,7 +116,6 @@ void X509_free(X509*); typedef struct BIO BIO; /* ASN stuff */ -typedef struct ASN1_TIME ASN1_TIME; @@ -345,8 +358,8 @@ long SSL_CTX_sess_set_cache_size(SSL_CTX*, long); long SSL_CTX_set_tmp_dh(SSL_CTX*, DH*); void OpenSSL_add_all_algorithms(void); -void SSL_library_init(); -void SSLeay_add_ssl_algorithms(void); +int SSL_library_init(); +int SSLeay_add_ssl_algorithms(void); SSL_CIPHER* SSL_get_current_cipher(SSL*); @@ -371,6 +384,10 @@ typedef unsigned char DES_cblock[8]; typedef const DES_cblock const_DES_cblock; typedef DES_cblock DES_key_schedule; +enum { + DES_ENCRYPT = 1, + DES_DECRYPT = 0 +}; const EVP_MD* EVP_md5(void); const EVP_CIPHER* EVP_des_ede3_cbc(void); @@ -392,6 +409,108 @@ int RAND_write_file(const char*); int RAND_load_file(const char*, long); +/* for libcurl */ +int RAND_status(void); + +int DES_set_key(const_DES_cblock*, DES_key_schedule*); +void DES_set_odd_parity(DES_cblock*); +void DES_ecb_encrypt(DES_cblock*, DES_cblock*, DES_key_schedule*, int); + +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX*, void* userdata); +void SSL_SESSION_free(SSL_SESSION* session); + +X509* SSL_get_certificate(SSL* ssl); +EVP_PKEY* SSL_get_privatekey(SSL* ssl); +EVP_PKEY* X509_get_pubkey(X509* x); + +int EVP_PKEY_copy_parameters(EVP_PKEY* to, const EVP_PKEY* from); +void EVP_PKEY_free(EVP_PKEY* pkey); +void ERR_error_string_n(unsigned long e, char *buf, size_t len); +void ERR_free_strings(void); +void EVP_cleanup(void); + +void* X509_get_ext_d2i(X509* x, int nid, int* crit, int* idx); + +#define GEN_IPADD 7 +#define NID_subject_alt_name 85 +#define STACK_OF(x) x + + +/* defined here because libcurl dereferences */ +typedef struct ASN1_STRING { + int type; + int length; + unsigned char* data; +} ASN1_STRING; + + +typedef struct GENERAL_NAME { + int type; + union { + ASN1_STRING* ia5; + } d; +} GENERAL_NAME; + +void GENERAL_NAMES_free(STACK_OF(GENERAL_NAME) *x); + +int sk_GENERAL_NAME_num(STACK_OF(GENERAL_NAME) *x); +GENERAL_NAME* sk_GENERAL_NAME_value(STACK_OF(GENERAL_NAME) *x, int i); + + +unsigned char* ASN1_STRING_data(ASN1_STRING* x); +int ASN1_STRING_length(ASN1_STRING* x); +int ASN1_STRING_type(ASN1_STRING *x); + +typedef ASN1_STRING X509_NAME_ENTRY; + +int X509_NAME_get_index_by_NID(X509_NAME* name,int nid, int lastpos); + +ASN1_STRING* X509_NAME_ENTRY_get_data(X509_NAME_ENTRY* ne); +X509_NAME_ENTRY* X509_NAME_get_entry(X509_NAME* name, int loc); + +#define OPENSSL_malloc(x) malloc(x) +#define OPENSSL_free(x) free(x) + +int ASN1_STRING_to_UTF8(unsigned char** out, ASN1_STRING* in); + +SSL_METHOD* SSLv23_client_method(void); /* doesn't actually roll back */ +SSL_METHOD* SSLv2_client_method(void); /* will never work, no v 2 */ + + +SSL_SESSION* SSL_get1_session(SSL* ssl); /* what's ref count */ + + +#define CRYPTO_free(x) free(x) +#define ASN1_TIME ASN1_STRING + +ASN1_TIME* X509_get_notBefore(X509* x); +ASN1_TIME* X509_get_notAfter(X509* x); + + +#define ASN1_UTCTIME ASN1_STRING +#define NID_commonName 13 +#define V_ASN1_UTF8STRING 12 +#define GEN_DNS 2 + + +typedef struct MD4_CTX { + void* ptr; +} MD4_CTX; + +void MD4_Init(MD4_CTX*); +void MD4_Update(MD4_CTX*, const void*, unsigned long); +void MD4_Final(unsigned char*, MD4_CTX*); + + +typedef struct MD5_CTX { + int buffer[32]; /* big enough to hold, check size in Init */ +} MD5_CTX; + +void MD5_Init(MD5_CTX*); +void MD5_Update(MD5_CTX*, const void*, unsigned long); +void MD5_Final(unsigned char*, MD5_CTX*); + + #define SSL_DEFAULT_CIPHER_LIST "" /* default all */ diff --git a/extra/yassl/include/openssl/x509.h b/extra/yassl/include/openssl/x509.h new file mode 100644 index 00000000000..dcd847c0337 --- /dev/null +++ b/extra/yassl/include/openssl/x509.h @@ -0,0 +1 @@ +/* x509.h for libcurl */ diff --git a/extra/yassl/include/openssl/x509v3.h b/extra/yassl/include/openssl/x509v3.h new file mode 100644 index 00000000000..adf94af8f48 --- /dev/null +++ b/extra/yassl/include/openssl/x509v3.h @@ -0,0 +1 @@ +/* x509v3.h for libcurl */ diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp index 935bae582ea..97ae468d2f9 100644 --- a/extra/yassl/include/yassl_int.hpp +++ b/extra/yassl/include/yassl_int.hpp @@ -34,6 +34,7 @@ #include "cert_wrapper.hpp" #include "log.hpp" #include "lock.hpp" +#include "openssl/ssl.h" // ASN1_STRING and DH namespace yaSSL { @@ -126,32 +127,70 @@ private: }; +// hold add crypt references provided to callers +class CryptProvider { + mySTL::list<Digest*> digestList_; + mySTL::list<BulkCipher*> cipherList_; + CryptProvider() {} // only GetCryptProvider creates +public: + ~CryptProvider(); + + Digest* NewMd5(); + BulkCipher* NewDesEde(); + + friend CryptProvider& GetCryptProvider(); +private: + CryptProvider(const CryptProvider&); // hide copy + CryptProvider& operator=(const CryptProvider&); // and assign +}; + +CryptProvider& GetCryptProvider(); + #undef X509_NAME // wincrypt.h clash // openSSL X509 names class X509_NAME { char* name_; + size_t sz_; + ASN1_STRING entry_; public: X509_NAME(const char*, size_t sz); ~X509_NAME(); char* GetName(); + ASN1_STRING* GetEntry(int i); private: X509_NAME(const X509_NAME&); // hide copy X509_NAME& operator=(const X509_NAME&); // and assign }; +class StringHolder { + ASN1_STRING asnString_; +public: + StringHolder(const char* str, int sz); + ~StringHolder(); + + ASN1_STRING* GetString(); +}; + + // openSSL X509 class X509 { X509_NAME issuer_; X509_NAME subject_; + StringHolder beforeDate_; // not valid before + StringHolder afterDate_; // not valid after public: - X509(const char* i, size_t, const char* s, size_t); + X509(const char* i, size_t, const char* s, size_t, + const char* b, int, const char* a, int); ~X509() {} X509_NAME* GetIssuer(); X509_NAME* GetSubject(); + + ASN1_STRING* GetBefore(); + ASN1_STRING* GetAfter(); private: X509(const X509&); // hide copy X509& operator=(const X509&); // and assign diff --git a/extra/yassl/include/yassl_types.hpp b/extra/yassl/include/yassl_types.hpp index bfb6467182b..76c807cd05f 100644 --- a/extra/yassl/include/yassl_types.hpp +++ b/extra/yassl/include/yassl_types.hpp @@ -35,10 +35,6 @@ namespace yaSSL { -// Delete static singleton memory holders -void CleanUp(); - - #ifdef YASSL_PURE_C // library allocation diff --git a/extra/yassl/lib/dummy b/extra/yassl/lib/dummy new file mode 100644 index 00000000000..85c1efd587f --- /dev/null +++ b/extra/yassl/lib/dummy @@ -0,0 +1 @@ +// this is a dummy file diff --git a/extra/yassl/mySTL/helpers.hpp b/extra/yassl/mySTL/helpers.hpp index 5aa14d838b1..df79025197a 100644 --- a/extra/yassl/mySTL/helpers.hpp +++ b/extra/yassl/mySTL/helpers.hpp @@ -44,6 +44,11 @@ return static_cast<void*>(d); } + // for compilers that want matching delete + inline void operator delete(void* ptr, Dummy* d) + { + } + typedef Dummy* yassl_pointer; namespace mySTL { diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp index b98c7faf1d0..ae609b510ba 100644 --- a/extra/yassl/src/cert_wrapper.cpp +++ b/extra/yassl/src/cert_wrapper.cpp @@ -271,10 +271,13 @@ int CertManager::Validate() else peerKeyType_ = dsa_sa_algo; - int iSz = cert.GetIssuer() ? strlen(cert.GetIssuer()) + 1 : 0; - int sSz = cert.GetCommonName() ? strlen(cert.GetCommonName()) + 1 : 0; + int iSz = strlen(cert.GetIssuer()) + 1; + int sSz = strlen(cert.GetCommonName()) + 1; + int bSz = strlen(cert.GetBeforeDate()) + 1; + int aSz = strlen(cert.GetAfterDate()) + 1; peerX509_ = NEW_YS X509(cert.GetIssuer(), iSz, cert.GetCommonName(), - sSz); + sSz, cert.GetBeforeDate(), bSz, + cert.GetAfterDate(), aSz); } return 0; } diff --git a/extra/yassl/src/make.bat b/extra/yassl/src/make.bat index 4c79a9c6406..148427a6f41 100644 --- a/extra/yassl/src/make.bat +++ b/extra/yassl/src/make.bat @@ -1,4 +1,4 @@ -# quick and dirty build file for testing different MSDEVs +REM quick and dirty build file for testing different MSDEVs setlocal set myFLAGS= /I../include /I../mySTL /I../taocrypt/include /W3 /c /ZI diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index 1aab14009d3..66196514a87 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -1,4 +1,4 @@ -/* ssl.cpp + /* ssl.cpp * * Copyright (C) 2003 Sawtooth Consulting Ltd. * @@ -36,6 +36,7 @@ #include "openssl/ssl.h" #include "handshake.hpp" #include "yassl_int.hpp" +#include "md5.hpp" // for TaoCrypt MD5 size assert #include <stdio.h> #ifdef _WIN32 @@ -52,6 +53,53 @@ namespace yaSSL { using mySTL::min; +int read_file(SSL_CTX* ctx, const char* file, int format, CertType type) +{ + if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM) + return SSL_BAD_FILETYPE; + + FILE* input = fopen(file, "rb"); + if (!input) + return SSL_BAD_FILE; + + if (type == CA) { + x509* ptr = PemToDer(file, Cert); + if (!ptr) { + fclose(input); + return SSL_BAD_FILE; + } + ctx->AddCA(ptr); // takes ownership + } + else { + x509*& x = (type == Cert) ? ctx->certificate_ : ctx->privateKey_; + + if (format == SSL_FILETYPE_ASN1) { + fseek(input, 0, SEEK_END); + long sz = ftell(input); + rewind(input); + x = NEW_YS x509(sz); // takes ownership + size_t bytes = fread(x->use_buffer(), sz, 1, input); + if (bytes != 1) { + fclose(input); + return SSL_BAD_FILE; + } + } + else { + x = PemToDer(file, type); + if (!x) { + fclose(input); + return SSL_BAD_FILE; + } + } + } + fclose(input); + return SSL_SUCCESS; +} + + +extern "C" { + + SSL_METHOD* SSLv3_method() { return SSLv3_client_method(); @@ -448,50 +496,6 @@ long SSL_CTX_set_tmp_dh(SSL_CTX* ctx, DH* dh) } -int read_file(SSL_CTX* ctx, const char* file, int format, CertType type) -{ - if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM) - return SSL_BAD_FILETYPE; - - FILE* input = fopen(file, "rb"); - if (!input) - return SSL_BAD_FILE; - - if (type == CA) { - x509* ptr = PemToDer(file, Cert); - if (!ptr) { - fclose(input); - return SSL_BAD_FILE; - } - ctx->AddCA(ptr); // takes ownership - } - else { - x509*& x = (type == Cert) ? ctx->certificate_ : ctx->privateKey_; - - if (format == SSL_FILETYPE_ASN1) { - fseek(input, 0, SEEK_END); - long sz = ftell(input); - rewind(input); - x = NEW_YS x509(sz); // takes ownership - size_t bytes = fread(x->use_buffer(), sz, 1, input); - if (bytes != 1) { - fclose(input); - return SSL_BAD_FILE; - } - } - else { - x = PemToDer(file, type); - if (!x) { - fclose(input); - return SSL_BAD_FILE; - } - } - } - fclose(input); - return SSL_SUCCESS; -} - - int SSL_CTX_use_certificate_file(SSL_CTX* ctx, const char* file, int format) { return read_file(ctx, file, format, Cert); @@ -723,8 +727,10 @@ void OpenSSL_add_all_algorithms() // compatibility only {} -void SSL_library_init() // compatiblity only -{} +int SSL_library_init() // compatiblity only +{ + return 1; +} DH* DH_new(void) @@ -804,15 +810,13 @@ const char* X509_verify_cert_error_string(long /* error */) const EVP_MD* EVP_md5(void) { - // TODO: FIX add to some list for destruction - return NEW_YS MD5; + return GetCryptProvider().NewMd5(); } const EVP_CIPHER* EVP_des_ede3_cbc(void) { - // TODO: FIX add to some list for destruction - return NEW_YS DES_EDE; + return GetCryptProvider().NewDesEde(); } @@ -897,6 +901,275 @@ void DES_ede3_cbc_encrypt(const byte* input, byte* output, long sz, } +// functions for libcurl +int RAND_status() +{ + return 1; /* TaoCrypt provides enough seed */ +} + + +int DES_set_key(const_DES_cblock* key, DES_key_schedule* schedule) +{ + memcpy(schedule, key, sizeof(const_DES_cblock)); + return 1; +} + + +void DES_set_odd_parity(DES_cblock* key) +{ + // not needed now for TaoCrypt +} + + +void DES_ecb_encrypt(DES_cblock* input, DES_cblock* output, + DES_key_schedule* key, int enc) +{ + DES des; + + if (enc) { + des.set_encryptKey(*key, 0); + des.encrypt(*output, *input, DES_BLOCK); + } + else { + des.set_decryptKey(*key, 0); + des.decrypt(*output, *input, DES_BLOCK); + } +} + + +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX*, void* userdata) +{ + // yaSSL doesn't support yet, unencrypt your PEM file with userdata + // before handing off to yaSSL +} + + +X509* SSL_get_certificate(SSL* ssl) +{ + // only used to pass to get_privatekey which isn't used + return 0; +} + + +EVP_PKEY* SSL_get_privatekey(SSL* ssl) +{ + // only called, not used + return 0; +} + + +void SSL_SESSION_free(SSL_SESSION* session) +{ + // managed by singleton +} + + + +EVP_PKEY* X509_get_pubkey(X509* x) +{ + // called, not used though + return 0; +} + + +int EVP_PKEY_copy_parameters(EVP_PKEY* to, const EVP_PKEY* from) +{ + // called, not used though + return 0; +} + + +void EVP_PKEY_free(EVP_PKEY* pkey) +{ + // never allocated from above +} + + +void ERR_error_string_n(unsigned long e, char *buf, size_t len) +{ + if (len) ERR_error_string(e, buf); +} + + +void ERR_free_strings(void) +{ + // handled internally +} + + +void EVP_cleanup(void) +{ + // nothing to do yet +} + + +ASN1_TIME* X509_get_notBefore(X509* x) +{ + if (x) return x->GetBefore(); + return 0; +} + + +ASN1_TIME* X509_get_notAfter(X509* x) +{ + if (x) return x->GetAfter(); + return 0; +} + + +SSL_METHOD* SSLv23_client_method(void) /* doesn't actually roll back */ +{ + return SSLv3_client_method(); +} + + +SSL_METHOD* SSLv2_client_method(void) /* will never work, no v 2 */ +{ + return 0; +} + + +SSL_SESSION* SSL_get1_session(SSL* ssl) /* what's ref count */ +{ + return SSL_get_session(ssl); +} + + +void GENERAL_NAMES_free(STACK_OF(GENERAL_NAME) *x) +{ + // no extension names supported yet +} + + +int sk_GENERAL_NAME_num(STACK_OF(GENERAL_NAME) *x) +{ + // no extension names supported yet + return 0; +} + + +GENERAL_NAME* sk_GENERAL_NAME_value(STACK_OF(GENERAL_NAME) *x, int i) +{ + // no extension names supported yet + return 0; +} + + +unsigned char* ASN1_STRING_data(ASN1_STRING* x) +{ + if (x) return x->data; + return 0; +} + + +int ASN1_STRING_length(ASN1_STRING* x) +{ + if (x) return x->length; + return 0; +} + + +int ASN1_STRING_type(ASN1_STRING *x) +{ + if (x) return x->type; + return 0; +} + + +int X509_NAME_get_index_by_NID(X509_NAME* name,int nid, int lastpos) +{ + int idx = -1; // not found + const char* start = &name->GetName()[lastpos + 1]; + + switch (nid) { + case NID_commonName: + const char* found = strstr(start, "/CN="); + if (found) { + found += 4; // advance to str + idx = found - start + lastpos + 1; + } + break; + } + + return idx; +} + + +ASN1_STRING* X509_NAME_ENTRY_get_data(X509_NAME_ENTRY* ne) +{ + // the same in yaSSL + return ne; +} + + +X509_NAME_ENTRY* X509_NAME_get_entry(X509_NAME* name, int loc) +{ + return name->GetEntry(loc); +} + + +// already formatted, caller responsible for freeing *out +int ASN1_STRING_to_UTF8(unsigned char** out, ASN1_STRING* in) +{ + if (!in) return 0; + + *out = (unsigned char*)malloc(in->length + 1); + if (*out) { + memcpy(*out, in->data, in->length); + (*out)[in->length] = 0; + } + return in->length; +} + + +void* X509_get_ext_d2i(X509* x, int nid, int* crit, int* idx) +{ + // no extensions supported yet + return 0; +} + + +void MD4_Init(MD4_CTX* md4) +{ + assert(0); // not yet supported, build compat. only +} + + +void MD4_Update(MD4_CTX* md4, const void* data, unsigned long sz) +{ +} + + +void MD4_Final(unsigned char* hash, MD4_CTX* md4) +{ +} + + +void MD5_Init(MD5_CTX* md5) +{ + // make sure we have a big enough buffer + typedef char ok[sizeof(md5->buffer) >= sizeof(TaoCrypt::MD5) ? 1 : -1]; + (void) sizeof(ok); + + // using TaoCrypt since no dynamic memory allocated + // and no destructor will be called + new (reinterpret_cast<yassl_pointer>(md5->buffer)) TaoCrypt::MD5(); +} + + +void MD5_Update(MD5_CTX* md5, const void* data, unsigned long sz) +{ + reinterpret_cast<TaoCrypt::MD5*>(md5->buffer)->Update( + static_cast<const byte*>(data), static_cast<unsigned int>(sz)); +} + + +void MD5_Final(unsigned char* hash, MD5_CTX* md5) +{ + reinterpret_cast<TaoCrypt::MD5*>(md5->buffer)->Final(hash); +} + + // functions for stunnel void RAND_screen() @@ -1098,8 +1371,10 @@ void DES_ede3_cbc_encrypt(const byte* input, byte* output, long sz, } - void SSLeay_add_ssl_algorithms() // compatibility only - {} + int SSLeay_add_ssl_algorithms() // compatibility only + { + return 1; + } void ERR_remove_state(unsigned long) @@ -1129,4 +1404,5 @@ void DES_ede3_cbc_encrypt(const byte* input, byte* output, long sz, // end stunnel needs +} // extern "C" } // namespace diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp index 5782df213ea..43b80d59a4d 100644 --- a/extra/yassl/src/template_instnt.cpp +++ b/extra/yassl/src/template_instnt.cpp @@ -31,7 +31,6 @@ #include "hmac.hpp" #include "md5.hpp" #include "sha.hpp" -#include "ripemd.hpp" #include "openssl/ssl.h" #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION @@ -51,12 +50,16 @@ template class list<yaSSL::SSL_SESSION*>; template class list<yaSSL::input_buffer*>; template class list<yaSSL::output_buffer*>; template class list<yaSSL::x509*>; +template class list<yaSSL::Digest*>; +template class list<yaSSL::BulkCipher*>; template void destroy<mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*>(mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*, mySTL::pair<int, yaSSL::ClientKeyBase* (*)()>*); template yaSSL::del_ptr_zero for_each<mySTL::list<TaoCrypt::Signer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<TaoCrypt::Signer*>::iterator, mySTL::list<TaoCrypt::Signer*>::iterator, yaSSL::del_ptr_zero); template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::SSL_SESSION*>::iterator, mySTL::list<yaSSL::SSL_SESSION*>::iterator, yaSSL::del_ptr_zero); template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::input_buffer*>::iterator, mySTL::list<yaSSL::input_buffer*>::iterator, yaSSL::del_ptr_zero); template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::output_buffer*>::iterator, mySTL::list<yaSSL::output_buffer*>::iterator, yaSSL::del_ptr_zero); template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::x509*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::x509*>::iterator, mySTL::list<yaSSL::x509*>::iterator, yaSSL::del_ptr_zero); +template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::Digest*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::Digest*>::iterator, mySTL::list<yaSSL::Digest*>::iterator, yaSSL::del_ptr_zero); +template yaSSL::del_ptr_zero for_each<mySTL::list<yaSSL::BulkCipher*>::iterator, yaSSL::del_ptr_zero>(mySTL::list<yaSSL::BulkCipher*>::iterator, mySTL::list<yaSSL::BulkCipher*>::iterator, yaSSL::del_ptr_zero); } namespace yaSSL { @@ -82,6 +85,7 @@ template void ysDelete<X509>(X509*); template void ysDelete<Message>(Message*); template void ysDelete<sslFactory>(sslFactory*); template void ysDelete<Sessions>(Sessions*); +template void ysDelete<CryptProvider>(CryptProvider*); template void ysArrayDelete<unsigned char>(unsigned char*); template void ysArrayDelete<char>(char*); } diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp index 1d2d5396ea0..4d6d1fc7aff 100644 --- a/extra/yassl/src/yassl_imp.cpp +++ b/extra/yassl/src/yassl_imp.cpp @@ -1975,7 +1975,9 @@ Connection::Connection(ProtocolVersion v, RandomPool& ran) : pre_master_secret_(0), sequence_number_(0), peer_sequence_number_(0), pre_secret_len_(0), send_server_key_(false), master_clean_(false), TLS_(v.major_ >= 3 && v.minor_ >= 1), version_(v), random_(ran) -{} +{ + memset(sessionID_, 0, sizeof(sessionID_)); +} Connection::~Connection() diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp index 396461a6ed5..f7fb1abfa3f 100644 --- a/extra/yassl/src/yassl_int.cpp +++ b/extra/yassl/src/yassl_int.cpp @@ -28,7 +28,6 @@ #include "yassl_int.hpp" #include "handshake.hpp" #include "timer.hpp" -#include "openssl/ssl.h" // for DH #ifdef YASSL_PURE_C @@ -1375,16 +1374,51 @@ Sessions& GetSessions() static sslFactory* sslFactoryInstance = 0; -sslFactory& GetSSL_Factory(){ +sslFactory& GetSSL_Factory() +{ if (!sslFactoryInstance) sslFactoryInstance = NEW_YS sslFactory; return *sslFactoryInstance; } -void CleanUp() +static CryptProvider* cryptProviderInstance = 0; + +CryptProvider& GetCryptProvider() +{ + if (!cryptProviderInstance) + cryptProviderInstance = NEW_YS CryptProvider; + return *cryptProviderInstance; +} + + +CryptProvider::~CryptProvider() +{ + mySTL::for_each(digestList_.begin(), digestList_.end(), del_ptr_zero()); + mySTL::for_each(cipherList_.begin(), cipherList_.end(), del_ptr_zero()); +} + + +Digest* CryptProvider::NewMd5() +{ + Digest* ptr = NEW_YS MD5(); + digestList_.push_back(ptr); + return ptr; +} + + +BulkCipher* CryptProvider::NewDesEde() +{ + BulkCipher* ptr = NEW_YS DES_EDE(); + cipherList_.push_back(ptr); + return ptr; +} + + +extern "C" void yaSSL_CleanUp() { TaoCrypt::CleanUp(); + ysDelete(cryptProviderInstance); ysDelete(sslFactoryInstance); ysDelete(sessionsInstance); } @@ -1978,18 +2012,20 @@ void Security::set_resuming(bool b) X509_NAME::X509_NAME(const char* n, size_t sz) - : name_(0) + : name_(0), sz_(sz) { if (sz) { name_ = NEW_YS char[sz]; memcpy(name_, n, sz); } + entry_.data = 0; } X509_NAME::~X509_NAME() { ysArrayDelete(name_); + ysArrayDelete(entry_.data); } @@ -1999,8 +2035,10 @@ char* X509_NAME::GetName() } -X509::X509(const char* i, size_t iSz, const char* s, size_t sSz) - : issuer_(i, iSz), subject_(s, sSz) +X509::X509(const char* i, size_t iSz, const char* s, size_t sSz, + const char* b, int bSz, const char* a, int aSz) + : issuer_(i, iSz), subject_(s, sSz), + beforeDate_(b, bSz), afterDate_(a, aSz) {} @@ -2016,6 +2054,61 @@ X509_NAME* X509::GetSubject() } +ASN1_STRING* X509::GetBefore() +{ + return beforeDate_.GetString(); +} + + +ASN1_STRING* X509::GetAfter() +{ + return afterDate_.GetString(); +} + + +ASN1_STRING* X509_NAME::GetEntry(int i) +{ + if (i < 0 || i >= int(sz_)) + return 0; + + if (entry_.data) + ysArrayDelete(entry_.data); + entry_.data = NEW_YS byte[sz_]; // max size; + + memcpy(entry_.data, &name_[i], sz_ - i); + if (entry_.data[sz_ -i - 1]) { + entry_.data[sz_ - i] = 0; + entry_.length = sz_ - i; + } + else + entry_.length = sz_ - i - 1; + entry_.type = 0; + + return &entry_; +} + + +StringHolder::StringHolder(const char* str, int sz) +{ + asnString_.length = sz; + asnString_.data = NEW_YS byte[sz + 1]; + memcpy(asnString_.data, str, sz); + asnString_.type = 0; // not used for now +} + + +StringHolder::~StringHolder() +{ + ysArrayDelete(asnString_.data); +} + + +ASN1_STRING* StringHolder::GetString() +{ + return &asnString_; +} + + } // namespace diff --git a/extra/yassl/taocrypt/benchmark/make.bat b/extra/yassl/taocrypt/benchmark/make.bat index 63391578cfa..4ebe4b32417 100644 --- a/extra/yassl/taocrypt/benchmark/make.bat +++ b/extra/yassl/taocrypt/benchmark/make.bat @@ -1,10 +1,9 @@ -# quick and dirty build file for testing different MSDEVs +REM quick and dirty build file for testing different MSDEVs setlocal set myFLAGS= /I../include /I../../mySTL /c /W3 /G6 /O2 -#set myFLAGS= /I../include /I../../mySTL /c /W3 cl %myFLAGS% benchmark.cpp -link.exe /out:benchmark.exe ../src/taocrypt.lib benchmark.obj +link.exe /out:benchmark.exe ../src/taocrypt.lib benchmark.obj advapi32.lib diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp index 6a1163fbb1c..da4c0ce1349 100644 --- a/extra/yassl/taocrypt/include/asn.hpp +++ b/extra/yassl/taocrypt/include/asn.hpp @@ -79,20 +79,27 @@ enum ASNIdFlag enum DNTags { - COMMON_NAME = 0x03 + COMMON_NAME = 0x03, // CN + SUR_NAME = 0x04, // SN + COUNTRY_NAME = 0x06, // C + LOCALITY_NAME = 0x07, // L + STATE_NAME = 0x08, // ST + ORG_NAME = 0x0a, // O + ORGUNIT_NAME = 0x0b // OU }; enum Constants { MIN_DATE_SZ = 13, - MAX_DATE_SZ = 15, + MAX_DATE_SZ = 16, MAX_ALGO_SZ = 16, MAX_LENGTH_SZ = 5, MAX_SEQ_SZ = 5, // enum(seq|con) + length(4) MAX_ALGO_SIZE = 9, MAX_DIGEST_SZ = 25, // SHA + enum(Bit or Octet) + length(4) - DSA_SIG_SZ = 40 + DSA_SIG_SZ = 40, + NAME_MAX = 512 // max total of all included names }; @@ -205,14 +212,14 @@ enum { SHA_SIZE = 20 }; // A Signing Authority class Signer { PublicKey key_; - char* name_; + char name_[NAME_MAX]; byte hash_[SHA_SIZE]; public: Signer(const byte* k, word32 kSz, const char* n, const byte* h); ~Signer(); const PublicKey& GetPublicKey() const { return key_; } - const char* GetCommonName() const { return name_; } + const char* GetName() const { return name_; } const byte* GetHash() const { return hash_; } private: @@ -245,6 +252,8 @@ public: const char* GetIssuer() const { return issuer_; } const char* GetCommonName() const { return subject_; } const byte* GetHash() const { return subjectHash_; } + const char* GetBeforeDate() const { return beforeDate_; } + const char* GetAfterDate() const { return afterDate_; } void DecodeToKey(); private: @@ -257,8 +266,10 @@ private: byte subjectHash_[SHA_SIZE]; // hash of all Names byte issuerHash_[SHA_SIZE]; // hash of all Names byte* signature_; - char* issuer_; // CommonName - char* subject_; // CommonName + char issuer_[NAME_MAX]; // Names + char subject_[NAME_MAX]; // Names + char beforeDate_[MAX_DATE_SZ]; // valid before date + char afterDate_[MAX_DATE_SZ]; // valid after date bool verify_; // Default to yes, but could be off void ReadHeader(); diff --git a/extra/yassl/taocrypt/include/runtime.hpp b/extra/yassl/taocrypt/include/runtime.hpp index 3a5cf62865a..09ca7524ef3 100644 --- a/extra/yassl/taocrypt/include/runtime.hpp +++ b/extra/yassl/taocrypt/include/runtime.hpp @@ -28,6 +28,10 @@ #ifndef yaSSL_NEW_HPP #define yaSSL_NEW_HPP +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifdef __sun diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp index 3efc26ab168..383fe65dea6 100644 --- a/extra/yassl/taocrypt/src/asn.cpp +++ b/extra/yassl/taocrypt/src/asn.cpp @@ -213,21 +213,17 @@ void PublicKey::AddToEnd(const byte* data, word32 len) Signer::Signer(const byte* k, word32 kSz, const char* n, const byte* h) - : key_(k, kSz), name_(0) + : key_(k, kSz) { - if (n) { int sz = strlen(n); - name_ = NEW_TC char[sz + 1]; memcpy(name_, n, sz); name_[sz] = 0; - } memcpy(hash_, h, SHA::DIGEST_SIZE); } Signer::~Signer() { - tcArrayDelete(name_); } @@ -424,17 +420,19 @@ void DH_Decoder::Decode(DH& key) CertDecoder::CertDecoder(Source& s, bool decode, SignerList* signers, bool noVerify, CertType ct) : BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0), - signature_(0), issuer_(0), subject_(0), verify_(!noVerify) + signature_(0), verify_(!noVerify) { + issuer_[0] = 0; + subject_[0] = 0; + if (decode) Decode(signers, ct); + } CertDecoder::~CertDecoder() { - tcArrayDelete(subject_); - tcArrayDelete(issuer_); tcArrayDelete(signature_); } @@ -672,8 +670,12 @@ void CertDecoder::GetName(NameType nt) SHA sha; word32 length = GetSequence(); // length of all distinguished names + assert (length < NAME_MAX); length += source_.get_index(); + char* ptr = (nt == ISSUER) ? issuer_ : subject_; + word32 idx = 0; + while (source_.get_index() < length) { GetSet(); GetSequence(); @@ -694,13 +696,49 @@ void CertDecoder::GetName(NameType nt) byte id = source_.next(); b = source_.next(); // strType word32 strLen = GetLength(source_); + bool copy = false; if (id == COMMON_NAME) { - char*& ptr = (nt == ISSUER) ? issuer_ : subject_; - ptr = NEW_TC char[strLen + 1]; - memcpy(ptr, source_.get_current(), strLen); - ptr[strLen] = 0; + memcpy(&ptr[idx], "/CN=", 4); + idx += 4; + copy = true; + } + else if (id == SUR_NAME) { + memcpy(&ptr[idx], "/SN=", 4); + idx += 4; + copy = true; + } + else if (id == COUNTRY_NAME) { + memcpy(&ptr[idx], "/C=", 3); + idx += 3; + copy = true; + } + else if (id == LOCALITY_NAME) { + memcpy(&ptr[idx], "/L=", 3); + idx += 3; + copy = true; + } + else if (id == STATE_NAME) { + memcpy(&ptr[idx], "/ST=", 4); + idx += 4; + copy = true; } + else if (id == ORG_NAME) { + memcpy(&ptr[idx], "/O=", 3); + idx += 3; + copy = true; + } + else if (id == ORGUNIT_NAME) { + memcpy(&ptr[idx], "/OU=", 4); + idx += 4; + copy = true; + } + + if (copy) { + memcpy(&ptr[idx], source_.get_current(), strLen); + idx += strLen; + } + sha.Update(source_.get_current(), strLen); source_.advance(strLen); } @@ -711,6 +749,8 @@ void CertDecoder::GetName(NameType nt) source_.advance(length); } } + ptr[idx++] = 0; + if (nt == ISSUER) sha.Final(issuerHash_); else @@ -744,6 +784,16 @@ void CertDecoder::GetDate(DateType dt) source_.SetError(BEFORE_DATE_E); else source_.SetError(AFTER_DATE_E); + + // save for later use + if (dt == BEFORE) { + memcpy(beforeDate_, date, length); + beforeDate_[length] = 0; + } + else { // after + memcpy(afterDate_, date, length); + afterDate_[length] = 0; + } } diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index 82a248ff7da..885ddfbf630 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -2428,7 +2428,7 @@ void PositiveMultiply(Integer& product, const Integer& a, const Integer& b) product.reg_.CleanNew(RoundupSize(aSize + bSize)); product.sign_ = Integer::POSITIVE; - WordBlock workspace(aSize + bSize); + AlignedWordBlock workspace(aSize + bSize); AsymmetricMultiply(product.reg_.get_buffer(), workspace.get_buffer(), a.reg_.get_buffer(), aSize, b.reg_.get_buffer(), bSize); } @@ -3375,7 +3375,7 @@ void PositiveDivide(Integer& remainder, Integer& quotient, quotient.reg_.CleanNew(RoundupSize(aSize-bSize+2)); quotient.sign_ = Integer::POSITIVE; - WordBlock T(aSize+2*bSize+4); + AlignedWordBlock T(aSize+2*bSize+4); Divide(remainder.reg_.get_buffer(), quotient.reg_.get_buffer(), T.get_buffer(), a.reg_.get_buffer(), aSize, b.reg_.get_buffer(), bSize); @@ -3595,7 +3595,7 @@ Integer Integer::InverseMod(const Integer &m) const return !u ? Zero() : (m*(*this-u)+1)/(*this); } - WordBlock T(m.reg_.size() * 4); + AlignedWordBlock T(m.reg_.size() * 4); Integer r((word)0, m.reg_.size()); unsigned k = AlmostInverse(r.reg_.get_buffer(), T.get_buffer(), reg_.get_buffer(), reg_.size(), diff --git a/extra/yassl/taocrypt/src/make.bat b/extra/yassl/taocrypt/src/make.bat index 5a2ae580b76..ecf7e8f8469 100644 --- a/extra/yassl/taocrypt/src/make.bat +++ b/extra/yassl/taocrypt/src/make.bat @@ -1,8 +1,7 @@ -# quick and dirty build file for testing different MSDEVs +REM quick and dirty build file for testing different MSDEVs setlocal set myFLAGS= /I../include /I../../mySTL /c /W3 /G6 /O2 -#set myFLAGS= /I../include /I../../mySTL /c /W3 /O1 cl %myFLAGS% aes.cpp cl %myFLAGS% aestables.cpp diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp index 3d0539187a7..4ef163a7f5d 100644 --- a/extra/yassl/taocrypt/src/misc.cpp +++ b/extra/yassl/taocrypt/src/misc.cpp @@ -25,6 +25,15 @@ #include "runtime.hpp" #include "misc.hpp" + +extern "C" { + + // for libcurl configure test, these are the signatures they use + // locking handled internally by library + char CRYPTO_lock() { return 0;} + char CRYPTO_add_lock() { return 0;} +} // extern "C" + #ifdef YASSL_PURE_C void* operator new(size_t sz, TaoCrypt::new_t) diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp index 12bcd8238f2..5efd2d32a10 100644 --- a/extra/yassl/taocrypt/src/template_instnt.cpp +++ b/extra/yassl/taocrypt/src/template_instnt.cpp @@ -30,11 +30,11 @@ #include "sha.hpp" #include "md5.hpp" #include "hmac.hpp" -#include "ripemd.hpp" #include "pwdbased.hpp" #include "algebra.hpp" #include "vector.hpp" #include "hash.hpp" +#include "ripemd.hpp" #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION namespace TaoCrypt { diff --git a/extra/yassl/taocrypt/taocrypt.dsp b/extra/yassl/taocrypt/taocrypt.dsp index 13b9a07419b..b741cef0096 100644 --- a/extra/yassl/taocrypt/taocrypt.dsp +++ b/extra/yassl/taocrypt/taocrypt.dsp @@ -64,7 +64,8 @@ LIB32=link.exe -lib # PROP Intermediate_Dir "Debug" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "..\mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "..\mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# SUBTRACT CPP /Fr # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe diff --git a/extra/yassl/taocrypt/test/make.bat b/extra/yassl/taocrypt/test/make.bat index e1a4cbce7cd..5f01db68d0d 100644 --- a/extra/yassl/taocrypt/test/make.bat +++ b/extra/yassl/taocrypt/test/make.bat @@ -1,4 +1,4 @@ -# quick and dirty build file for testing different MSDEVs +REM quick and dirty build file for testing different MSDEVs setlocal set myFLAGS= /I../include /I../../mySTL /c /W3 /G6 /O2 diff --git a/extra/yassl/testsuite/make.bat b/extra/yassl/testsuite/make.bat index d8a55b0d3af..1bc7ce0513d 100644 --- a/extra/yassl/testsuite/make.bat +++ b/extra/yassl/testsuite/make.bat @@ -1,4 +1,4 @@ -# quick and dirty build file for testing different MSDEVs +REM quick and dirty build file for testing different MSDEVs setlocal set myFLAGS= /I../include /I../taocrypt/include /I../mySTL /c /W3 /G6 /O2 /MT /D"WIN32" /D"NO_MAIN_DRIVER" diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp index 79d02b63558..259975fba0b 100644 --- a/extra/yassl/testsuite/test.hpp +++ b/extra/yassl/testsuite/test.hpp @@ -27,7 +27,7 @@ #endif /* _WIN32 */ -#if defined(__MACH__) || defined(_WIN32) +#if !defined(_SOCKLEN_T) && (defined(__MACH__) || defined(_WIN32)) typedef int socklen_t; #endif @@ -305,8 +305,8 @@ inline void showPeer(SSL* ssl) char* subject = X509_NAME_oneline(X509_get_subject_name(peer), 0, 0); printf("peer's cert info:\n"); - printf("issuer is: %s\n", issuer); - printf("subject is: %s\n", subject); + printf("issuer : %s\n", issuer); + printf("subject: %s\n", subject); free(subject); free(issuer); diff --git a/extra/yassl/testsuite/testsuite.cpp b/extra/yassl/testsuite/testsuite.cpp index af988432a86..1cf6a78ebe7 100644 --- a/extra/yassl/testsuite/testsuite.cpp +++ b/extra/yassl/testsuite/testsuite.cpp @@ -91,6 +91,7 @@ int main(int argc, char** argv) assert(memcmp(input, output, sizeof(input)) == 0); printf("\nAll tests passed!\n"); + yaSSL_CleanUp(); return 0; } @@ -146,10 +147,10 @@ int test_openSSL_des() (byte*)key, iv); byte cipher[16]; - DES_ede3_cbc_encrypt((byte*)data, cipher, dataSz, &key[0], &key[8], - &key[16], &iv, true); + DES_ede3_cbc_encrypt((byte*)data, cipher, dataSz, &key[0], &key[1], + &key[2], &iv, true); byte plain[16]; - DES_ede3_cbc_encrypt(cipher, plain, 16, &key[0], &key[8], &key[16], + DES_ede3_cbc_encrypt(cipher, plain, 16, &key[0], &key[1], &key[2], &iv, false); return 0; } diff --git a/extra/yassl/testsuite/testsuite.dsp b/extra/yassl/testsuite/testsuite.dsp index f896aa7f020..24c325fa878 100644 --- a/extra/yassl/testsuite/testsuite.dsp +++ b/extra/yassl/testsuite/testsuite.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX- /O2 /I "../taocrypt/include" /I "../include" /I "../mySTL" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /YX /FD /c +# ADD CPP /nologo /MT /W3 /O2 /I "../taocrypt/include" /I "../include" /I "../mySTL" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -67,7 +67,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX- /ZI /Od /I "../taocrypt/include" /I "../include" /I "../mySTL" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /FR /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "../taocrypt/include" /I "../include" /I "../mySTL" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe diff --git a/include/my_dbug.h b/include/my_dbug.h index b76a3fcc8c9..6e60b599f53 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -40,6 +40,7 @@ extern void _db_doprnt_ _VARARGS((const char *format,...)); extern void _db_dump_(uint _line_,const char *keyword,const char *memory, uint length); extern void _db_output_(uint flag); +extern void _db_end_(void); extern void _db_lock_file(void); extern void _db_unlock_file(void); @@ -66,6 +67,7 @@ extern void _db_unlock_file(void); #define DBUG_IN_USE (_db_fp_ && _db_fp_ != stderr) #define DEBUGGER_OFF _no_db_=1;_db_on_=0; #define DEBUGGER_ON _no_db_=0 +#define DBUG_END() _db_end_ () #define DBUG_LOCK_FILE { _db_lock_file(); } #define DBUG_UNLOCK_FILE { _db_unlock_file(); } #define DBUG_OUTPUT(A) { _db_output_(A); } @@ -90,6 +92,7 @@ extern void _db_unlock_file(void); #define DBUG_IN_USE 0 #define DEBUGGER_OFF #define DEBUGGER_ON +#define DBUG_END() #define DBUG_LOCK_FILE #define DBUG_UNLOCK_FILE #define DBUG_OUTPUT(A) diff --git a/include/my_pthread.h b/include/my_pthread.h index 202e047dc4e..3e4388413e0 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -332,12 +332,14 @@ int sigwait(sigset_t *setp, int *sigp); /* Use our implemention */ we want to make sure that no such flags are set. */ #if defined(HAVE_SIGACTION) && !defined(my_sigset) -#define my_sigset(A,B) do { struct sigaction s; sigset_t set; \ +#define my_sigset(A,B) do { struct sigaction s; sigset_t set; int rc; \ + DBUG_ASSERT((A) != 0); \ sigemptyset(&set); \ s.sa_handler = (B); \ s.sa_mask = set; \ s.sa_flags = 0; \ - sigaction((A), &s, (struct sigaction *) NULL); \ + rc= sigaction((A), &s, (struct sigaction *) NULL);\ + DBUG_ASSERT(rc == 0); \ } while (0) #elif defined(HAVE_SIGSET) && !defined(my_sigset) #define my_sigset(A,B) sigset((A),(B)) diff --git a/include/my_sys.h b/include/my_sys.h index 65a295ee39e..229389f1ac5 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -75,6 +75,7 @@ extern int NEAR my_errno; /* Last error in mysys */ #define MY_CHECK_ERROR 1 /* Params to my_end; Check open-close */ #define MY_GIVE_INFO 2 /* Give time info about process*/ +#define MY_DONT_FREE_DBUG 4 /* Do not call DBUG_END() in my_end() */ #define ME_HIGHBYTE 8 /* Shift for colours */ #define ME_NOCUR 1 /* Don't use curses message */ diff --git a/include/mysql.h b/include/mysql.h index 6217ce631b5..3a71e47f414 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -149,7 +149,8 @@ enum mysql_option MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT, MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION, MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, - MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT + MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT, + MYSQL_OPT_SSL_VERIFY_SERVER_CERT }; struct st_mysql_options { @@ -164,6 +165,7 @@ struct st_mysql_options { char *ssl_ca; /* PEM CA file */ char *ssl_capath; /* PEM directory of CA-s? */ char *ssl_cipher; /* cipher to use */ + my_bool ssl_verify_server_cert; /* if to verify server cert */ char *shared_memory_base_name; unsigned long max_allowed_packet; my_bool use_ssl; /* if to use SSL or not */ diff --git a/include/sslopt-longopts.h b/include/sslopt-longopts.h index 99271571329..0435ddb815a 100644 --- a/include/sslopt-longopts.h +++ b/include/sslopt-longopts.h @@ -37,5 +37,10 @@ {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format (implies --ssl).", (gptr*) &opt_ssl_key, (gptr*) &opt_ssl_key, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - +#ifdef MYSQL_CLIENT + {"ssl-verify-server-cert", OPT_SSL_VERIFY_SERVER_CERT, + "Verify server's \"Common Name\" in its cert against hostname used when connecting. This option is disabled by default.", + (gptr*) &opt_ssl_verify_server_cert, (gptr*) &opt_ssl_verify_server_cert, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, +#endif #endif /* HAVE_OPENSSL */ diff --git a/include/sslopt-vars.h b/include/sslopt-vars.h index 3b9b10c82e7..7204145fc28 100644 --- a/include/sslopt-vars.h +++ b/include/sslopt-vars.h @@ -26,4 +26,7 @@ SSL_STATIC char *opt_ssl_capath = 0; SSL_STATIC char *opt_ssl_cert = 0; SSL_STATIC char *opt_ssl_cipher = 0; SSL_STATIC char *opt_ssl_key = 0; +#ifdef MYSQL_CLIENT +SSL_STATIC my_bool opt_ssl_verify_server_cert= 0; +#endif #endif diff --git a/include/violite.h b/include/violite.h index b48f3724f5b..fd870177c68 100644 --- a/include/violite.h +++ b/include/violite.h @@ -105,33 +105,22 @@ void vio_timeout(Vio *vio,uint which, uint timeout); #include <openssl/ssl.h> #include <openssl/err.h> -struct st_VioSSLAcceptorFd +struct st_VioSSLFd { SSL_CTX *ssl_context; - SSL_METHOD *ssl_method; - struct st_VioSSLAcceptorFd *session_id_context; }; -/* One copy for client */ -struct st_VioSSLConnectorFd -{ - SSL_CTX *ssl_context; - /* function pointers which are only once for SSL client */ - SSL_METHOD *ssl_method; -}; - -int sslaccept(struct st_VioSSLAcceptorFd*, Vio *, long timeout); -int sslconnect(struct st_VioSSLConnectorFd*, Vio *, long timeout); +int sslaccept(struct st_VioSSLFd*, Vio *, long timeout); +int sslconnect(struct st_VioSSLFd*, Vio *, long timeout); -struct st_VioSSLConnectorFd +struct st_VioSSLFd *new_VioSSLConnectorFd(const char *key_file, const char *cert_file, const char *ca_file, const char *ca_path, const char *cipher); -struct st_VioSSLAcceptorFd +struct st_VioSSLFd *new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, const char *ca_file,const char *ca_path, const char *cipher); -Vio *new_VioSSL(struct st_VioSSLAcceptorFd *fd, Vio *sd, int state); #endif /* HAVE_OPENSSL */ #ifdef HAVE_SMEM @@ -140,6 +129,8 @@ int vio_write_shared_memory(Vio *vio, const gptr buf, int size); int vio_close_shared_memory(Vio * vio); #endif +void vio_end(void); + #ifdef __cplusplus } #endif @@ -204,7 +195,9 @@ struct st_vio my_bool (*was_interrupted)(Vio*); int (*vioclose)(Vio*); void (*timeout)(Vio*, unsigned int which, unsigned int timeout); +#ifdef HAVE_OPENSSL void *ssl_arg; +#endif #ifdef HAVE_SMEM HANDLE handle_file_map; char *handle_map; diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 3b8f7576049..df819b73ea6 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -3700,6 +3700,37 @@ os_aio_posix_handle( #endif /************************************************************************** +Do a 'last millisecond' check that the page end is sensible; +reported page checksum errors from Linux seem to wipe over the page end. */ +static +void +os_file_check_page_trailers( +/*========================*/ + byte* combined_buf, /* in: combined write buffer */ + ulint total_len) /* in: size of combined_buf, in bytes + (a multiple of UNIV_PAGE_SIZE) */ +{ + ulint len; + + for (len = 0; len + UNIV_PAGE_SIZE <= total_len; + len += UNIV_PAGE_SIZE) { + byte* buf = combined_buf + len; + + if (memcmp(buf + (FIL_PAGE_LSN + 4), buf + (UNIV_PAGE_SIZE + - FIL_PAGE_END_LSN_OLD_CHKSUM + 4), 4)) { + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: ERROR: The page to be written seems corrupt!\n" +"InnoDB: Writing a block of %lu bytes, currently at offset %lu\n", + (ulong)total_len, (ulong)len); + buf_page_print(buf); + fprintf(stderr, +"InnoDB: ERROR: The page to be written seems corrupt!\n"); + } + } +} + +/************************************************************************** Does simulated aio. This function should be called by an i/o-handler thread. */ @@ -3736,7 +3767,6 @@ os_aio_simulated_handle( ibool ret; ulint n; ulint i; - ulint len2; segment = os_aio_get_array_and_local_segment(&array, global_segment); @@ -3943,33 +3973,16 @@ consecutive_loop: (ulong) total_len); ut_error; } - - /* Do a 'last millisecond' check that the page end - is sensible; reported page checksum errors from - Linux seem to wipe over the page end */ - - for (len2 = 0; len2 + UNIV_PAGE_SIZE <= total_len; - len2 += UNIV_PAGE_SIZE) { - if (mach_read_from_4(combined_buf + len2 - + FIL_PAGE_LSN + 4) - != mach_read_from_4(combined_buf + len2 - + UNIV_PAGE_SIZE - - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { - ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: ERROR: The page to be written seems corrupt!\n"); - fprintf(stderr, -"InnoDB: Writing a block of %lu bytes, currently writing at offset %lu\n", - (ulong)total_len, (ulong)len2); - buf_page_print(combined_buf + len2); - fprintf(stderr, -"InnoDB: ERROR: The page to be written seems corrupt!\n"); - } - } + + os_file_check_page_trailers(combined_buf, total_len); } - + ret = os_file_write(slot->name, slot->file, combined_buf, slot->offset, slot->offset_high, total_len); + + if (array == os_aio_write_array) { + os_file_check_page_trailers(combined_buf, total_len); + } } else { ret = os_file_read(slot->file, combined_buf, slot->offset, slot->offset_high, total_len); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index bfec476fde3..c1e0703af10 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -178,7 +178,7 @@ void STDCALL mysql_server_end() /* If library called my_init(), free memory allocated by it */ if (!org_my_init_done) { - my_end(0); + my_end(MY_DONT_FREE_DBUG); #ifndef THREAD /* Remove TRACING, if enabled by mysql_debug() */ DBUG_POP(); @@ -188,6 +188,7 @@ void STDCALL mysql_server_end() mysql_thread_end(); finish_client_errs(); free_charsets(); + vio_end(); mysql_client_init= org_my_init_done= 0; #ifdef EMBEDDED_SERVER if (stderror_file) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 33598748397..73074397086 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -100,15 +100,15 @@ install-data-local: uninstall-local: @RM@ -f -r $(DESTDIR)$(testdir) -std_data/client-key.pem: +std_data/client-key.pem: $(top_srcdir)/SSL/$(@F) @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data -std_data/client-cert.pem: +std_data/client-cert.pem: $(top_srcdir)/SSL/$(@F) @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data -std_data/cacert.pem: +std_data/cacert.pem: $(top_srcdir)/SSL/$(@F) @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data -std_data/server-cert.pem: +std_data/server-cert.pem: $(top_srcdir)/SSL/$(@F) @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data -std_data/server-key.pem: +std_data/server-key.pem: $(top_srcdir)/SSL/$(@F) @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data SUFFIXES = .sh diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index 973655a3eb6..6fa6bc73bdb 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -20,6 +20,7 @@ sub mtr_record_dead_children (); sub mtr_exit ($); sub sleep_until_file_created ($$$); sub mtr_kill_processes ($); +sub mtr_kill_process ($$$$); # static in C sub spawn_impl ($$$$$$$$); @@ -885,6 +886,25 @@ sub mtr_kill_processes ($) { } } + +sub mtr_kill_process ($$$$) { + my $pid= shift; + my $signal= shift; + my $retries= shift; + my $timeout= shift; + + while (1) + { + kill($signal, $pid); + + last unless kill (0, $pid) and $retries--; + + mtr_debug("Sleep $timeout second waiting for processes to die"); + + sleep($timeout); + } +} + ############################################################################## # # When we exit, we kill off all children diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 25c1f6c1ddc..4a9628c0721 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -134,7 +134,6 @@ our $glob_win32= 0; # OS and native Win32 executables our $glob_win32_perl= 0; # ActiveState Win32 Perl our $glob_cygwin_perl= 0; # Cygwin Perl our $glob_cygwin_shell= undef; -our $glob_use_libtool= 1; our $glob_mysql_test_dir= undef; our $glob_mysql_bench_dir= undef; our $glob_hostname= undef; @@ -189,6 +188,7 @@ our $exe_slave_mysqld; our $exe_im; our $exe_my_print_defaults; our $lib_udf_example; +our $exe_libtool; our $opt_bench= 0; our $opt_small_bench= 0; @@ -376,7 +376,6 @@ sub main () { check_ndbcluster_support(); # We check whether to actually use it later check_ssl_support(); - check_running_as_root(); environment_setup(); signal_setup(); @@ -443,12 +442,6 @@ sub initial_setup () { $glob_cygwin_perl= ($^O eq "cygwin"); $glob_win32= ($glob_win32_perl or $glob_cygwin_perl); - # Use libtool on all platforms except windows - if ( $glob_win32 ) - { - $glob_use_libtool= 0; - } - # We require that we are in the "mysql-test" directory # to run mysql-test-run @@ -925,6 +918,7 @@ sub command_line_setup () { path_err => "$opt_vardir/log/im.err", path_log => "$opt_vardir/log/im.log", path_pid => "$opt_vardir/run/im.pid", + path_angel_pid => "$opt_vardir/run/im.angel.pid", path_sock => "$sockdir/im.sock", port => $im_port, start_timeout => $master->[0]->{'start_timeout'}, @@ -1000,6 +994,21 @@ sub snapshot_setup () { sub executable_setup () { + # + # Check if libtool is available in this distribution/clone + # we need it when valgrinding or debugging non installed binary + # Otherwise valgrind will valgrind the libtool wrapper or bash + # and gdb will not find the real executable to debug + # + if ( -x "../libtool") + { + $exe_libtool= "../libtool"; + if ($opt_valgrind or $glob_debugger) + { + mtr_report("Using \"$exe_libtool\" when running valgrind or debugger"); + } + } + if ( $opt_source_dist ) { if ( $glob_win32 ) @@ -1180,6 +1189,7 @@ sub environment_setup () { $ENV{'NDB_STATUS_OK'}= "YES"; $ENV{'IM_PATH_PID'}= $instance_manager->{path_pid}; + $ENV{'IM_PATH_ANGEL_PID'}= $instance_manager->{path_angel_pid}; $ENV{'IM_PORT'}= $instance_manager->{port}; $ENV{'IM_MYSQLD1_SOCK'}= $instance_manager->{instances}->[0]->{path_sock}; @@ -1336,7 +1346,7 @@ sub kill_and_cleanup () { sub check_running_as_root () { # Check if running as root # i.e a file can be read regardless what mode we set it to - my $test_file= "test_running_as_root.txt"; + my $test_file= "$opt_vardir/test_running_as_root.txt"; mtr_tofile($test_file, "MySQL"); chmod(oct("0000"), $test_file); @@ -1653,6 +1663,7 @@ sub initialize_servers () { save_installed_db(); } } + check_running_as_root(); } } @@ -1804,6 +1815,7 @@ sub im_create_defaults_file($) { [manager] pid-file = $instance_manager->{path_pid} +angel-pid-file = $instance_manager->{path_angel_pid} socket = $instance_manager->{path_sock} port = $instance_manager->{port} password-file = $instance_manager->{password_file} @@ -1828,7 +1840,7 @@ log-slow-queries = $instance->{path_datadir}/mysqld$server_id.slow.log language = $path_language character-sets-dir = $path_charsetsdir basedir = $path_my_basedir -server_id =$server_id +server_id = $server_id skip-stack-trace skip-innodb skip-bdb @@ -2625,6 +2637,15 @@ sub mysqld_start ($$$$$) { $exe= undef; } + if ($exe_libtool and $opt_valgrind) + { + # Add "libtool --mode-execute" + # if running in valgrind(to avoid valgrinding bash) + unshift(@$args, "--mode=execute", $exe); + $exe= $exe_libtool; + } + + if ( $type eq 'master' ) { if ( ! defined $exe or @@ -2787,6 +2808,18 @@ sub im_start($$) { sub im_stop($) { my $instance_manager = shift; + # Obtain mysqld-process pids before we start stopping IM (it can delete pid + # files). + + my @mysqld_pids = (); + my $instances = $instance_manager->{'instances'}; + + push(@mysqld_pids, mtr_get_pid_from_file($instances->[0]->{'path_pid'})) + if -r $instances->[0]->{'path_pid'}; + + push(@mysqld_pids, mtr_get_pid_from_file($instances->[1]->{'path_pid'})) + if -r $instances->[1]->{'path_pid'}; + # Re-read pid from the file, since during tests Instance Manager could have # been restarted, so its pid could have been changed. @@ -2794,34 +2827,79 @@ sub im_stop($) { mtr_get_pid_from_file($instance_manager->{'path_pid'}) if -f $instance_manager->{'path_pid'}; + if (-f $instance_manager->{'path_angel_pid'}) + { + $instance_manager->{'angel_pid'} = + mtr_get_pid_from_file($instance_manager->{'path_angel_pid'}) + } + else + { + $instance_manager->{'angel_pid'} = undef; + } + # Inspired from mtr_stop_mysqld_servers(). start_reap_all(); - # Create list of pids. We should stop Instance Manager and all started - # mysqld-instances. Some of them may be nonguarded, so IM will not stop them - # on shutdown. + # Try graceful shutdown. - my @pids = ( $instance_manager->{'pid'} ); - my $instances = $instance_manager->{'instances'}; + mtr_kill_process($instance_manager->{'pid'}, 'TERM', 10, 1); - if ( -r $instances->[0]->{'path_pid'} ) + # Check that all processes died. + + my $clean_shutdown= 0; + + while (1) { - push(@pids, mtr_get_pid_from_file($instances->[0]->{'path_pid'})); + last if kill (0, $instance_manager->{'pid'}); + + last if (defined $instance_manager->{'angel_pid'}) && + kill (0, $instance_manager->{'angel_pid'}); + + foreach my $pid (@mysqld_pids) + { + last if kill (0, $pid); + } + + $clean_shutdown= 1; + last; } - if ( -r $instances->[1]->{'path_pid'} ) + # Kill leftovers (the order is important). + + unless ($clean_shutdown) { - push(@pids, mtr_get_pid_from_file($instances->[1]->{'path_pid'})); - } + mtr_kill_process($instance_manager->{'angel_pid'}, 'KILL', 10, 1) + if defined $instance_manager->{'angel_pid'}; + + mtr_kill_process($instance_manager->{'pid'}, 'KILL', 10, 1); + + # Shutdown managed mysqld-processes. Some of them may be nonguarded, so IM + # will not stop them on shutdown. So, we should firstly try to end them + # legally. + + mtr_kill_processes(\@mysqld_pids); - # Kill processes. + # Complain in error log so that a warning will be shown. + + my $errlog= "$opt_vardir/log/mysql-test-run.pl.err"; + + open (ERRLOG, ">>$errlog") || + mtr_error("Can not open error log ($errlog)"); + + my $ts= localtime(); + print ERRLOG + "Warning: [$ts] Instance Manager did not shutdown gracefully.\n"; + + close ERRLOG; + } - mtr_kill_processes(\@pids); + # That's all. stop_reap_all(); $instance_manager->{'pid'} = undef; + $instance_manager->{'angel_pid'} = undef; } @@ -3122,12 +3200,12 @@ sub run_mysqltest ($) { debugger_arguments(\$args, \$exe, "client"); } - if ($glob_use_libtool and $opt_valgrind) + if ($exe_libtool and $opt_valgrind) { # Add "libtool --mode-execute" before the test to execute # if running in valgrind(to avoid valgrinding bash) unshift(@$args, "--mode=execute", $exe); - $exe= "libtool"; + $exe= $exe_libtool; } if ( $opt_check_testcases ) @@ -3197,9 +3275,9 @@ sub gdb_arguments { mtr_add_arg($$args, "$type"); mtr_add_arg($$args, "-e"); - if ( $glob_use_libtool ) + if ( $exe_libtool ) { - mtr_add_arg($$args, "libtool"); + mtr_add_arg($$args, $exe_libtool); mtr_add_arg($$args, "--mode=execute"); } @@ -3259,9 +3337,9 @@ sub ddd_arguments { my $save_exe= $$exe; $$args= []; - if ( $glob_use_libtool ) + if ( $exe_libtool ) { - $$exe= "libtool"; + $$exe= $exe_libtool; mtr_add_arg($$args, "--mode=execute"); mtr_add_arg($$args, "ddd"); } @@ -3282,6 +3360,8 @@ sub debugger_arguments { my $exe= shift; my $debugger= $opt_debugger || $opt_client_debugger; + # FIXME Need to change the below "eq"'s to + # "case unsensitive string contains" if ( $debugger eq "vcexpress" or $debugger eq "vc") { # vc[express] /debugexe exe arg1 .. argn diff --git a/mysql-test/r/blackhole.result b/mysql-test/r/blackhole.result index 140d7e73d48..a4c057f256c 100644 --- a/mysql-test/r/blackhole.result +++ b/mysql-test/r/blackhole.result @@ -123,3 +123,11 @@ master-bin.000001 # Query 1 # use `test`; create table t3 like t1 master-bin.000001 # Query 1 # use `test`; insert into t1 select * from t3 master-bin.000001 # Query 1 # use `test`; replace into t1 select * from t3 drop table t1,t2,t3; +drop table if exists t1; +Warnings: +Note 1051 Unknown table 't1' +create table t1 (c char(20)) engine=MyISAM; +insert into t1 values ("Monty"),("WAX"),("Walrus"); +alter table t1 engine=blackhole; +ERROR HY000: Table storage engine for 't1' doesn't have this option +drop table t1; diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index 8349d6e9338..cf358e6a404 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -103,8 +103,8 @@ t1 CREATE TABLE `t1` ( `c2` varchar(1) character set latin1 collate latin1_danish_ci NOT NULL default '', `c3` varbinary(1) NOT NULL default '', `c4` varbinary(1) NOT NULL default '', - `c5` varbinary(3) NOT NULL default '', - `c6` varbinary(3) NOT NULL default '', + `c5` varbinary(4) NOT NULL default '', + `c6` varbinary(4) NOT NULL default '', `c7` decimal(2,1) NOT NULL default '0.0', `c8` decimal(2,1) NOT NULL default '0.0', `c9` decimal(2,1) default NULL, @@ -152,11 +152,11 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `COALESCE(1)` int(1) NOT NULL default '0', - `COALESCE(1.0)` decimal(2,1) unsigned NOT NULL default '0.0', + `COALESCE(1.0)` decimal(2,1) NOT NULL default '0.0', `COALESCE('a')` varchar(1) NOT NULL default '', `COALESCE(1,1.0)` decimal(2,1) NOT NULL default '0.0', `COALESCE(1,'1')` varbinary(1) NOT NULL default '', - `COALESCE(1.1,'1')` varbinary(3) NOT NULL default '', + `COALESCE(1.1,'1')` varbinary(4) NOT NULL default '', `COALESCE('a' COLLATE latin1_bin,'b')` varchar(1) character set latin1 collate latin1_bin NOT NULL default '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result index a6ad95570f8..89b17d69f40 100644 --- a/mysql-test/r/distinct.result +++ b/mysql-test/r/distinct.result @@ -533,3 +533,15 @@ select count(distinct concat(x,y)) from t1; count(distinct concat(x,y)) 2 drop table t1; +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a,b)); +INSERT INTO t1 VALUES (1, 101); +INSERT INTO t1 SELECT a + 1, a + 101 FROM t1; +INSERT INTO t1 SELECT a + 2, a + 102 FROM t1; +INSERT INTO t1 SELECT a + 4, a + 104 FROM t1; +INSERT INTO t1 SELECT a + 8, a + 108 FROM t1; +EXPLAIN SELECT DISTINCT a,a FROM t1 WHERE b < 12 ORDER BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 8 NULL 16 Using where; Using index +SELECT DISTINCT a,a FROM t1 WHERE b < 12 ORDER BY a; +a a +DROP TABLE t1; diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result index d66dec741bd..75e1548cdee 100644 --- a/mysql-test/r/explain.result +++ b/mysql-test/r/explain.result @@ -53,3 +53,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE ÔÁ ref ÉÎÄ0,ÉÎÄ01 ÉÎÄ0 5 const 1 Using where; Using index drop table ÔÁÂ; set names latin1; +select 3 into @v1; +explain select 3 into @v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index e3257ce5fd0..e38e2624e19 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -326,3 +326,20 @@ deallocate prepare s; set @str=NULL; drop table t2; drop table t1; +create table t1 ( +some_id smallint(5) unsigned, +key (some_id) +); +insert into t1 values (1),(2); +select some_id from t1 where some_id not in(2,-1); +some_id +1 +select some_id from t1 where some_id not in(-4,-1,-4); +some_id +1 +2 +select some_id from t1 where some_id not in(-4,-1,3423534,2342342); +some_id +1 +2 +drop table t1; diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index aed79e7f8fa..a17661d26d0 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1017,6 +1017,13 @@ t 1000000 1 drop table t1; +select load_file("lkjlkj"); +load_file("lkjlkj") +NULL +select ifnull(load_file("lkjlkj"),"it's null"); +ifnull(load_file("lkjlkj"),"it's null") +it's null +End of 4.1 tests create table t1 (d decimal default null); insert into t1 values (null); select format(d, 2) from t1; @@ -1039,4 +1046,10 @@ cast(ltrim(' 20.06 ') as decimal(19,2)) select cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2)); cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2)) 20.06 +select conv("18383815659218730760",10,10) + 0; +conv("18383815659218730760",10,10) + 0 +1.8383815659219e+19 +select "18383815659218730760" + 0; +"18383815659218730760" + 0 +1.8383815659219e+19 End of 5.0 tests diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index fdb4a0c5996..0e029802555 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -732,6 +732,25 @@ SELECT count(*) FROM t1 WHERE d>FROM_DAYS(TO_DAYS(@TMP)) AND d<=FROM_DAYS(TO_DAY count(*) 3 DROP TABLE t1; +select last_day('2005-00-00'); +last_day('2005-00-00') +NULL +Warnings: +Warning 1292 Truncated incorrect datetime value: '2005-00-00' +select last_day('2005-00-01'); +last_day('2005-00-01') +NULL +Warnings: +Warning 1292 Truncated incorrect datetime value: '2005-00-01' +select last_day('2005-01-00'); +last_day('2005-01-00') +NULL +Warnings: +Warning 1292 Truncated incorrect datetime value: '2005-01-00' +select monthname(str_to_date(null, '%m')), monthname(str_to_date(null, '%m')), +monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m')); +monthname(str_to_date(null, '%m')) monthname(str_to_date(null, '%m')) monthname(str_to_date(1, '%m')) monthname(str_to_date(0, '%m')) +NULL NULL January NULL explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1, timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a2; id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 6370f7699b3..f9b55cc6a7b 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2116,3 +2116,25 @@ COUNT(DISTINCT a) 1 DROP TABLE t1; DROP PROCEDURE a; +CREATE TABLE t1 (a varchar(64) NOT NULL default '', PRIMARY KEY(a)); +INSERT INTO t1 (a) VALUES +(''), ('CENTRAL'), ('EASTERN'), ('GREATER LONDON'), +('NORTH CENTRAL'), ('NORTH EAST'), ('NORTH WEST'), ('SCOTLAND'), +('SOUTH EAST'), ('SOUTH WEST'), ('WESTERN'); +EXPLAIN SELECT DISTINCT a,a FROM t1 ORDER BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL PRIMARY 66 NULL 12 Using index for group-by +SELECT DISTINCT a,a FROM t1 ORDER BY a; +a a + +CENTRAL CENTRAL +EASTERN EASTERN +GREATER LONDON GREATER LONDON +NORTH CENTRAL NORTH CENTRAL +NORTH EAST NORTH EAST +NORTH WEST NORTH WEST +SCOTLAND SCOTLAND +SOUTH EAST SOUTH EAST +SOUTH WEST SOUTH WEST +WESTERN WESTERN +DROP TABLE t1; diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result index a37f260ff31..68b13b5fc0a 100644 --- a/mysql-test/r/having.result +++ b/mysql-test/r/having.result @@ -12,7 +12,7 @@ explain extended select count(a) as b from t1 where a=0 having b >=0; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables Warnings: -Note 1003 select count(`test`.`t1`.`a`) AS `b` from `test`.`t1` where 0 having (count(`test`.`t1`.`a`) >= 0) +Note 1003 select count(`test`.`t1`.`a`) AS `b` from `test`.`t1` where 0 having (`b` >= 0) drop table t1; CREATE TABLE t1 ( raw_id int(10) NOT NULL default '0', diff --git a/mysql-test/r/im_options_set.result b/mysql-test/r/im_options_set.result index 0d2fa699fc7..5e6c740624e 100644 --- a/mysql-test/r/im_options_set.result +++ b/mysql-test/r/im_options_set.result @@ -1,11 +1,11 @@ -server_id =1 -server_id =2 +server_id = 1 +server_id = 2 SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 SET mysqld1.server_id = 11; server_id =11 -server_id =2 +server_id = 2 SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 diff --git a/mysql-test/r/im_options_unset.result b/mysql-test/r/im_options_unset.result index 834152c35d2..bf54025edb7 100644 --- a/mysql-test/r/im_options_unset.result +++ b/mysql-test/r/im_options_unset.result @@ -1,10 +1,10 @@ -server_id =1 -server_id =2 +server_id = 1 +server_id = 2 SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 UNSET mysqld1.server_id; -server_id =2 +server_id = 2 SHOW VARIABLES LIKE 'server_id'; Variable_name Value server_id 1 diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index d5fb046d319..633b11e1f1b 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1083,11 +1083,6 @@ DROP TABLE t1; DROP VIEW v1; DROP FUNCTION func1; DROP FUNCTION func2; -create database mysqltest; -create table mysqltest.t1(a int); -select table_schema from information_schema.tables where table_schema='mysqltest'; -table_schema -drop database mysqltest; select column_type, group_concat(table_schema, '.', table_name), count(*) as num from information_schema.columns where table_schema='information_schema' and @@ -1096,3 +1091,20 @@ group by column_type order by num; column_type group_concat(table_schema, '.', table_name) num varchar(20) information_schema.COLUMNS 1 varchar(7) information_schema.ROUTINES,information_schema.VIEWS 2 +create table t1(f1 char(1) not null, f2 char(9) not null) +default character set utf8; +select CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH from +information_schema.columns where table_schema='test' and table_name = 't1'; +CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH +1 3 +9 27 +drop table t1; +use mysql; +INSERT INTO `proc` VALUES ('test','','PROCEDURE','','SQL','CONTAINS_SQL', +'NO','DEFINER','','','BEGIN\r\n \r\nEND','root@%','2006-03-02 18:40:03', +'2006-03-02 18:40:03','',''); +select routine_name from information_schema.routines; +routine_name + +delete from proc where name=''; +use test; diff --git a/mysql-test/r/information_schema_chmod.result b/mysql-test/r/information_schema_chmod.result new file mode 100644 index 00000000000..36124559439 --- /dev/null +++ b/mysql-test/r/information_schema_chmod.result @@ -0,0 +1,5 @@ +create database mysqltest; +create table mysqltest.t1(a int); +select table_schema from information_schema.tables where table_schema='mysqltest'; +table_schema +drop database mysqltest; diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index ecf76d477a0..86288caf398 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -700,8 +700,8 @@ ERROR 42S22: Unknown column 't1.b' in 'on clause' select * from information_schema.statistics join information_schema.columns using(table_name,column_name) where table_name='user'; TABLE_NAME COLUMN_NAME TABLE_CATALOG TABLE_SCHEMA NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT TABLE_CATALOG TABLE_SCHEMA ORDINAL_POSITION COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES COLUMN_COMMENT -user Host NULL mysql 0 mysql PRIMARY 1 A NULL NULL NULL BTREE NULL mysql 1 NO char 20 60 NULL NULL utf8 utf8_bin char(60) PRI select,insert,update,references -user User NULL mysql 0 mysql PRIMARY 2 A 5 NULL NULL BTREE NULL mysql 2 NO char 5 16 NULL NULL utf8 utf8_bin char(16) PRI select,insert,update,references +user Host NULL mysql 0 mysql PRIMARY 1 A NULL NULL NULL BTREE NULL mysql 1 NO char 60 180 NULL NULL utf8 utf8_bin char(60) PRI select,insert,update,references +user User NULL mysql 0 mysql PRIMARY 2 A 5 NULL NULL BTREE NULL mysql 2 NO char 16 48 NULL NULL utf8 utf8_bin char(16) PRI select,insert,update,references drop table t1; drop table t2; drop table t3; diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 694bab2597c..eae023813b5 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -1151,6 +1151,63 @@ EXPLAIN SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%' OR FALSE; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index PRIMARY,name name 23 NULL 3 Using where; Using index -1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using where; Using index +1 SIMPLE t2 index NULL fkey 5 NULL 5 Using index +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.fkey 1 Using where +DROP TABLE t1,t2; +DROP VIEW IF EXISTS v1,v2; +DROP TABLE IF EXISTS t1,t2; +CREATE TABLE t1 (a int); +CREATE table t2 (b int); +INSERT INTO t1 VALUES (1), (2), (3), (4), (1), (1), (3); +INSERT INTO t2 VALUES (2), (3); +CREATE VIEW v1 AS SELECT a FROM t1 JOIN t2 ON t1.a=t2.b; +CREATE VIEW v2 AS SELECT b FROM t2 JOIN t1 ON t2.b=t1.a; +SELECT v1.a, v2. b +FROM v1 LEFT OUTER JOIN v2 ON (v1.a=v2.b) AND (v1.a >= 3) +GROUP BY v1.a; +a b +2 NULL +3 3 +SELECT v1.a, v2. b +FROM { OJ v1 LEFT OUTER JOIN v2 ON (v1.a=v2.b) AND (v1.a >= 3) } +GROUP BY v1.a; +a b +2 NULL +3 3 +DROP VIEW v1,v2; +DROP TABLE t1,t2; +CREATE TABLE t1 (a int); +CREATE TABLE t2 (b int); +INSERT INTO t1 VALUES (1), (2), (3), (4); +INSERT INTO t2 VALUES (2), (3); +SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1=1); +a b +1 NULL +2 2 +3 3 +4 NULL +SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1 OR 1); +a b +1 NULL +2 2 +3 3 +4 NULL +SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (0 OR 1); +a b +1 NULL +2 2 +3 3 +4 NULL +SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1=1 OR 2=2); +a b +1 NULL +2 2 +3 3 +4 NULL +SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1=1 OR 1=0); +a b +1 NULL +2 2 +3 3 +4 NULL DROP TABLE t1,t2; diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 58e1f86b3f9..9a34d6fba58 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -768,3 +768,11 @@ Table Op Msg_type Msg_text test.t1 check status OK test.t2 check status OK drop table t1, t2, t3; +drop table if exists t1; +Warnings: +Note 1051 Unknown table 't1' +create table t1 (c char(20)) engine=MyISAM; +insert into t1 values ("Monty"),("WAX"),("Walrus"); +alter table t1 engine=MERGE; +ERROR HY000: Table storage engine for 't1' doesn't have this option +drop table t1; diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result index 0a170e16188..50b0b6ae294 100644 --- a/mysql-test/r/metadata.result +++ b/mysql-test/r/metadata.result @@ -2,7 +2,7 @@ drop table if exists t1,t2; select 1, 1.0, -1, "hello", NULL; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def 1 8 1 1 N 32897 0 63 -def 1.0 246 3 3 N 161 1 63 +def 1.0 246 4 3 N 129 1 63 def -1 8 2 2 N 32897 0 63 def hello 253 5 5 N 1 31 8 def NULL 6 0 0 Y 32896 0 63 diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index a067d3ad0f8..4b7084e813c 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -74,7 +74,7 @@ c_cp932 +----------------------+------------+--------+ | >a < | b | 123421 | | >a < | 0123456789 | 4 | -| >abcd< | NULL | 4 | +| >abcd< | | 4 | +----------------------+------------+--------+ +------+------+---------------------------+ | i | j | k | @@ -94,6 +94,14 @@ c_cp932 | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | i | int(11) | YES | | NULL | | -| j | int(11) | NO | | NULL | | +| j | int(11) | NO | | | | | k | int(11) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ ++------+------+ +| i | s1 | ++------+------+ +| 1 | x | +| 2 | NULL | +| 3 | | ++------+------+ +End of 5.0 tests diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index 50e4cc28d93..664833fab2a 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -189,4 +189,5 @@ HEX(f) select HEX(f) from t4; HEX(f) 835C +flush logs; drop table t1, t2, t03, t04, t3, t4; diff --git a/mysql-test/r/ndb_autodiscover3.result b/mysql-test/r/ndb_autodiscover3.result new file mode 100644 index 00000000000..8bc1b968436 --- /dev/null +++ b/mysql-test/r/ndb_autodiscover3.result @@ -0,0 +1,45 @@ +drop table if exists t1, t2; +create table t1 (a int key) engine=ndbcluster; +begin; +insert into t1 values (1); +insert into t1 values (2); +ERROR HY000: Got temporary error 4025 'Node failure caused abort of transaction' from ndbcluster +commit; +ERROR HY000: Got error 4350 'Transaction already aborted' from ndbcluster +drop table t1; +create table t2 (a int, b int, primary key(a,b)) engine=ndbcluster; +insert into t2 values (1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1); +select * from t2 order by a limit 3; +a b +1 1 +2 1 +3 1 +create table t2 (a int key) engine=ndbcluster; +insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +select * from t2 order by a limit 3; +a +1 +2 +3 +select * from t2 order by a limit 3; +ERROR HY000: Can't lock file (errno: 241) +select * from t2 order by a limit 3; +a +1 +2 +3 +show tables; +Tables_in_test +create table t2 (a int key) engine=ndbcluster; +insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +select * from t2 order by a limit 3; +a +1 +2 +3 +select * from t2 order by a limit 3; +a +1 +2 +3 +drop table t2; diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result index 91382619b6c..1fcfb11525e 100644 --- a/mysql-test/r/openssl_1.result +++ b/mysql-test/r/openssl_1.result @@ -3,8 +3,8 @@ create table t1(f1 int); insert into t1 values (5); grant select on test.* to ssl_user1@localhost require SSL; grant select on test.* to ssl_user2@localhost require cipher "DHE-RSA-AES256-SHA"; -grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com"; -grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com"; +grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/emailAddress=abstract.mysql.developer@mysql.com"; +grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/emailAddress=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/emailAddress=abstract.mysql.developer@mysql.com"; flush privileges; SHOW STATUS LIKE 'Ssl_cipher'; Variable_name Value @@ -41,3 +41,10 @@ ERROR 42000: DELETE command denied to user 'ssl_user4'@'localhost' for table 't1 drop user ssl_user1@localhost, ssl_user2@localhost, ssl_user3@localhost, ssl_user4@localhost; drop table t1; +mysqltest: Could not open connection 'default': 2026 SSL connection error +mysqltest: Could not open connection 'default': 2026 SSL connection error +mysqltest: Could not open connection 'default': 2026 SSL connection error +Error when connection to server using SSL:Unable to get private key from '' +mysqltest: Could not open connection 'default': 2026 SSL connection error +Error when connection to server using SSL:Unable to get certificate from '' +mysqltest: Could not open connection 'default': 2026 SSL connection error diff --git a/mysql-test/r/outfile.result b/mysql-test/r/outfile.result Binary files differindex ee8c3249c9d..040dff576f8 100644 --- a/mysql-test/r/outfile.result +++ b/mysql-test/r/outfile.result diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 603de2afe4e..207d9ea7475 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -1777,7 +1777,7 @@ Table Create Table t5 CREATE TABLE `t5` ( `const01` bigint(1) NOT NULL default '0', `param01` bigint(20) default NULL, - `const02` decimal(2,1) unsigned NOT NULL default '0.0', + `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, `const03` double NOT NULL default '0', `param03` double default NULL, @@ -1807,7 +1807,7 @@ select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def test t5 t5 const01 const01 8 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 -def test t5 t5 const02 const02 246 3 3 N 33 1 63 +def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 def test t5 t5 const03 const03 5 17 1 N 32769 31 63 def test t5 t5 param03 param03 5 23 1 Y 32768 31 63 diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 9e635f60f14..13aa549949c 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -1760,7 +1760,7 @@ Table Create Table t5 CREATE TABLE `t5` ( `const01` bigint(1) NOT NULL default '0', `param01` bigint(20) default NULL, - `const02` decimal(2,1) unsigned NOT NULL default '0.0', + `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, `const03` double NOT NULL default '0', `param03` double default NULL, @@ -1790,7 +1790,7 @@ select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def test t5 t5 const01 const01 8 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 -def test t5 t5 const02 const02 246 3 3 N 33 1 63 +def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 def test t5 t5 const03 const03 5 17 1 N 32769 31 63 def test t5 t5 param03 param03 5 23 1 Y 32768 31 63 diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index fd51c71cad6..a08dae945bd 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -1761,7 +1761,7 @@ Table Create Table t5 CREATE TABLE `t5` ( `const01` bigint(1) NOT NULL default '0', `param01` bigint(20) default NULL, - `const02` decimal(2,1) unsigned NOT NULL default '0.0', + `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, `const03` double NOT NULL default '0', `param03` double default NULL, @@ -1791,7 +1791,7 @@ select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def test t5 t5 const01 const01 8 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 -def test t5 t5 const02 const02 246 3 3 N 33 1 63 +def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 def test t5 t5 const03 const03 5 17 1 N 32769 31 63 def test t5 t5 param03 param03 5 23 1 Y 32768 31 63 diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 876f7615672..6682b085097 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -1697,7 +1697,7 @@ Table Create Table t5 CREATE TABLE `t5` ( `const01` bigint(1) NOT NULL default '0', `param01` bigint(20) default NULL, - `const02` decimal(2,1) unsigned NOT NULL default '0.0', + `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, `const03` double NOT NULL default '0', `param03` double default NULL, @@ -1727,7 +1727,7 @@ select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def test t5 t5 const01 const01 8 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 -def test t5 t5 const02 const02 246 3 3 N 33 1 63 +def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 def test t5 t5 const03 const03 5 17 1 N 32769 31 63 def test t5 t5 param03 param03 5 23 1 Y 32768 31 63 @@ -4711,7 +4711,7 @@ Table Create Table t5 CREATE TABLE `t5` ( `const01` bigint(1) NOT NULL default '0', `param01` bigint(20) default NULL, - `const02` decimal(2,1) unsigned NOT NULL default '0.0', + `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, `const03` double NOT NULL default '0', `param03` double default NULL, @@ -4741,7 +4741,7 @@ select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def test t5 t5 const01 const01 8 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 -def test t5 t5 const02 const02 246 3 3 N 33 1 63 +def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 def test t5 t5 const03 const03 5 17 1 N 32769 31 63 def test t5 t5 param03 param03 5 23 1 Y 32768 31 63 diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index c39621d184f..dc3b984949d 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -1760,7 +1760,7 @@ Table Create Table t5 CREATE TABLE `t5` ( `const01` bigint(1) NOT NULL default '0', `param01` bigint(20) default NULL, - `const02` decimal(2,1) unsigned NOT NULL default '0.0', + `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, `const03` double NOT NULL default '0', `param03` double default NULL, @@ -1790,7 +1790,7 @@ select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def test t5 t5 const01 const01 8 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 -def test t5 t5 const02 const02 246 3 3 N 33 1 63 +def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 def test t5 t5 const03 const03 5 17 1 N 32769 31 63 def test t5 t5 param03 param03 5 23 1 Y 32768 31 63 diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index 7c83099311e..000a20da655 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -1760,7 +1760,7 @@ Table Create Table t5 CREATE TABLE `t5` ( `const01` bigint(1) NOT NULL default '0', `param01` bigint(20) default NULL, - `const02` decimal(2,1) unsigned NOT NULL default '0.0', + `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, `const03` double NOT NULL default '0', `param03` double default NULL, @@ -1790,7 +1790,7 @@ select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def test t5 t5 const01 const01 8 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 -def test t5 t5 const02 const02 246 3 3 N 33 1 63 +def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 def test t5 t5 const03 const03 5 17 1 N 32769 31 63 def test t5 t5 param03 param03 5 23 1 Y 32768 31 63 diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result index 42e7712750c..751dc7754f7 100644 --- a/mysql-test/r/rpl_temporary.result +++ b/mysql-test/r/rpl_temporary.result @@ -103,17 +103,24 @@ f 1 drop temporary table t4; drop table t5; -set @session.pseudo_thread_id=100; +set @@session.pseudo_thread_id=100; create temporary table t101 (id int); create temporary table t102 (id int); -set @session.pseudo_thread_id=200; +set @@session.pseudo_thread_id=200; create temporary table t201 (id int); -create temporary table `#not_user_table_prefixed_with_hash_sign_no_harm` (id int); -set @con1_id=connection_id(); -kill @con1_id; +create temporary table `t``201` (id int); +create temporary table `#sql_not_user_table202` (id int); +set @@session.pseudo_thread_id=300; +create temporary table t301 (id int); +create temporary table t302 (id int); +create temporary table `#sql_not_user_table303` (id int); create table t1(f int); insert into t1 values (1); select * from t1 /* must be 1 */; f 1 drop table t1; +select * from t1; +a +1 +drop table t1; diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result index b584e04ed57..60b956785ba 100644 --- a/mysql-test/r/rpl_until.result +++ b/mysql-test/r/rpl_until.result @@ -29,9 +29,40 @@ n 2 3 4 -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 319 # Master master-bin.000001 319 No # +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_MYPORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 776 +Relay_Log_File slave-relay-bin.000004 +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running # +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 319 +Relay_Log_Space # +Until_Condition Master +Until_Log_File master-bin.000001 +Until_Log_Pos 319 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; select * from t1; n @@ -39,23 +70,116 @@ n 2 3 4 -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 319 # Master master-no-such-bin.000001 291 No # +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_MYPORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 776 +Relay_Log_File slave-relay-bin.000004 +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running # +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 319 +Relay_Log_Space # +Until_Condition Master +Until_Log_File master-no-such-bin.000001 +Until_Log_Pos 291 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746; select * from t2; n 1 2 -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 608 # Relay slave-relay-bin.000004 746 No # +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_MYPORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 776 +Relay_Log_File slave-relay-bin.000004 +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running # +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 608 +Relay_Log_Space # +Until_Condition Relay +Until_Log_File slave-relay-bin.000004 +Until_Log_Pos 746 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # start slave; stop slave; start slave until master_log_file='master-bin.000001', master_log_pos=776; -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 776 # Master master-bin.000001 776 No # +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_MYPORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 776 +Relay_Log_File slave-relay-bin.000004 +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 776 +Relay_Log_Space # +Until_Condition Master +Until_Log_File master-bin.000001 +Until_Log_Pos 776 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # start slave until master_log_file='master-bin', master_log_pos=561; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12; diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index ea85025a37b..335637b787f 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -3411,3 +3411,38 @@ SELECT * FROM t1; i 255 DROP TABLE t1; +create table t1 (a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t2 (a int, b int, c int, e int, primary key(a,b,c)); +insert into t2 select A.a, B.a, C.a, C.a from t1 A, t1 B, t1 C; +analyze table t2; +Table Op Msg_type Msg_text +test.t2 analyze status OK +select 'In next EXPLAIN, B.rows must be exactly 10:' Z; +Z +In next EXPLAIN, B.rows must be exactly 10: +explain select * from t2 A, t2 B where A.a=5 and A.b=5 and A.C<5 +and B.a=5 and B.b=A.e and (B.b =1 or B.b = 3 or B.b=5); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE A range PRIMARY PRIMARY 12 NULL 3 Using where +1 SIMPLE B ref PRIMARY PRIMARY 8 const,test.A.e 10 +drop table t1, t2; +CREATE TABLE t1 (a int PRIMARY KEY, b int, INDEX(b)); +INSERT INTO t1 VALUES (1, 3), (9,4), (7,5), (4,5), (6,2), +(3,1), (5,1), (8,9), (2,2), (0,9); +CREATE TABLE t2 (c int, d int, f int, INDEX(c,f)); +INSERT INTO t2 VALUES +(1,0,0), (1,0,1), (2,0,0), (2,0,1), (3,0,0), (4,0,1), +(5,0,0), (5,0,1), (6,0,0), (0,0,1), (7,0,0), (7,0,1), +(0,0,0), (0,0,1), (8,0,0), (8,0,1), (9,0,0), (9,0,1); +EXPLAIN +SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using where +1 SIMPLE t2 ref c c 5 test.t1.a 2 Using where +EXPLAIN +SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6 AND a > 0; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using where +1 SIMPLE t2 ref c c 5 test.t1.a 2 Using where +DROP TABLE t1, t2; diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index a49b282ddb7..924963017eb 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -282,9 +282,9 @@ select @tmp_x, @tmp_y, @tmp_z| @tmp_x @tmp_y @tmp_z 42 45 87 call p(42, 43, @tmp_z)| -ERROR 42000: OUT or INOUT argument 2 for routine test.p is not a variable +ERROR 42000: OUT or INOUT argument 2 for routine test.p is not a variable or NEW pseudo-variable in BEFORE trigger call p(42, @tmp_y, 43)| -ERROR 42000: OUT or INOUT argument 3 for routine test.p is not a variable +ERROR 42000: OUT or INOUT argument 3 for routine test.p is not a variable or NEW pseudo-variable in BEFORE trigger drop procedure p| create procedure p() begin end| lock table t1 read| diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 59ce1d13d2b..746cd8f00d4 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4904,4 +4904,60 @@ schema_name select routine_name,routine_schema from information_schema.routines where routine_schema like 'bug18344%'| routine_name routine_schema +drop function if exists bug12472| +create function bug12472() returns int return (select count(*) from t1)| +create table t3 as select bug12472() as i| +show create table t3| +Table Create Table +t3 CREATE TABLE `t3` ( + `i` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select * from t3| +i +0 +drop table t3| +create view v1 as select bug12472() as j| +create table t3 as select * from v1| +show create table t3| +Table Create Table +t3 CREATE TABLE `t3` ( + `j` bigint(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select * from t3| +j +0 +drop table t3| +drop view v1| +drop function bug12472| +DROP FUNCTION IF EXISTS bug18589_f1| +DROP PROCEDURE IF EXISTS bug18589_p1| +DROP PROCEDURE IF EXISTS bug18589_p2| +CREATE FUNCTION bug18589_f1(arg TEXT) RETURNS TEXT +BEGIN +RETURN CONCAT(arg, ""); +END| +CREATE PROCEDURE bug18589_p1(arg TEXT, OUT ret TEXT) +BEGIN +SET ret = CONCAT(arg, ""); +END| +CREATE PROCEDURE bug18589_p2(arg TEXT) +BEGIN +DECLARE v TEXT; +CALL bug18589_p1(arg, v); +SELECT v; +END| +SELECT bug18589_f1(REPEAT("a", 767))| +bug18589_f1(REPEAT("a", 767)) +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +SET @bug18589_v1 = ""| +CALL bug18589_p1(REPEAT("a", 767), @bug18589_v1)| +SELECT @bug18589_v1| +@bug18589_v1 +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +CALL bug18589_p2(REPEAT("a", 767))| +v +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DROP FUNCTION bug18589_f1| +DROP PROCEDURE bug18589_p1| +DROP PROCEDURE bug18589_p2| drop table t1,t2; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 14b05238e14..056457a4786 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1480,7 +1480,7 @@ Note 1003 select `test`.`t1`.`s1` AS `s1`,not(<in_optimizer>(`test`.`t1`.`s1`,<e explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 Using index -2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 1 Using index; Using where +2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index; Using where Warnings: Note 1003 select `test`.`t1`.`s1` AS `s1`,not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where (`test`.`t2`.`s1` < _latin1'a2'))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1` drop table t1,t2; @@ -3169,3 +3169,17 @@ create table t2 (a int, b int); insert into t2 values (2, 1), (1, 0); delete from t1 where c <= 1140006215 and (select b from t2 where a = 2) = 1; drop table t1, t2; +CREATE TABLE t1 (a INT); +CREATE VIEW v1 AS SELECT * FROM t1 WHERE no_such_column = ANY (SELECT 1); +ERROR 42S22: Unknown column 'no_such_column' in 'where clause' +CREATE VIEW v2 AS SELECT * FROM t1 WHERE no_such_column = (SELECT 1); +ERROR 42S22: Unknown column 'no_such_column' in 'where clause' +SELECT * FROM t1 WHERE no_such_column = ANY (SELECT 1); +ERROR 42S22: Unknown column 'no_such_column' in 'IN/ALL/ANY subquery' +DROP TABLE t1; +create table t1 (i int, j bigint); +insert into t1 values (1, 2), (2, 2), (3, 2); +select * from (select min(i) from t1 where j=(select * from (select min(j) from t1) t2)) t3; +min(i) +1 +drop table t1; diff --git a/mysql-test/r/trigger-grant.result b/mysql-test/r/trigger-grant.result index 87e5e11d779..f6384d479b7 100644 --- a/mysql-test/r/trigger-grant.result +++ b/mysql-test/r/trigger-grant.result @@ -310,3 +310,87 @@ SELECT @mysqltest_var; Hello, world! DROP USER mysqltest_u1@localhost; DROP DATABASE mysqltest_db1; +DELETE FROM mysql.user WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.db WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.tables_priv WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.columns_priv WHERE User LIKE 'mysqltest_%'; +FLUSH PRIVILEGES; +DROP DATABASE IF EXISTS mysqltest_db1; +CREATE DATABASE mysqltest_db1; +USE mysqltest_db1; +CREATE TABLE t1 (i1 INT); +CREATE TABLE t2 (i1 INT); +CREATE USER mysqltest_dfn@localhost; +CREATE USER mysqltest_inv@localhost; +GRANT EXECUTE, CREATE ROUTINE, SUPER ON *.* TO mysqltest_dfn@localhost; +GRANT INSERT ON mysqltest_db1.* TO mysqltest_inv@localhost; +CREATE PROCEDURE p1(OUT i INT) DETERMINISTIC NO SQL SET i = 3; +CREATE PROCEDURE p2(INOUT i INT) DETERMINISTIC NO SQL SET i = i * 5; +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW +CALL p1(NEW.i1); +CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW +CALL p2(NEW.i1); +INSERT INTO t1 VALUES (7); +ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't1' +INSERT INTO t2 VALUES (11); +ERROR 42000: SELECT,UPDATE command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't2' +DROP TRIGGER t2_bi; +DROP TRIGGER t1_bi; +GRANT SELECT ON mysqltest_db1.* TO mysqltest_dfn@localhost; +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW +CALL p1(NEW.i1); +CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW +CALL p2(NEW.i1); +INSERT INTO t1 VALUES (13); +ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't1' +INSERT INTO t2 VALUES (17); +ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't2' +REVOKE SELECT ON mysqltest_db1.* FROM mysqltest_dfn@localhost; +DROP TRIGGER t2_bi; +DROP TRIGGER t1_bi; +GRANT UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost; +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW +CALL p1(NEW.i1); +CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW +CALL p2(NEW.i1); +INSERT INTO t1 VALUES (19); +INSERT INTO t2 VALUES (23); +ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't2' +REVOKE UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost; +DROP TRIGGER t2_bi; +DROP TRIGGER t1_bi; +GRANT SELECT, UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost; +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW +CALL p1(NEW.i1); +CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW +CALL p2(NEW.i1); +INSERT INTO t1 VALUES (29); +INSERT INTO t2 VALUES (31); +REVOKE SELECT, UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost; +DROP TRIGGER t2_bi; +DROP TRIGGER t1_bi; +DROP PROCEDURE p2; +DROP PROCEDURE p1; +GRANT UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost; +CREATE PROCEDURE p1(OUT i INT) DETERMINISTIC NO SQL SET i = 37; +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW +CALL p1(NEW.i1); +INSERT INTO t1 VALUES (41); +DROP PROCEDURE p1; +CREATE PROCEDURE p1(IN i INT) DETERMINISTIC NO SQL SET @v1 = i + 43; +INSERT INTO t1 VALUES (47); +ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't1' +DROP PROCEDURE p1; +CREATE PROCEDURE p1(INOUT i INT) DETERMINISTIC NO SQL SET i = i + 51; +INSERT INTO t1 VALUES (53); +ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't1' +DROP PROCEDURE p1; +REVOKE UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost; +DROP TRIGGER t1_bi; +DROP USER mysqltest_inv@localhost; +DROP USER mysqltest_dfn@localhost; +DROP TABLE t2; +DROP TABLE t1; +DROP DATABASE mysqltest_db1; +USE test; +End of 5.0 tests. diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 6a689437482..8b4aba367fb 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -998,3 +998,95 @@ SELECT * FROM t1 WHERE conn_id != trigger_conn_id; conn_id trigger_conn_id DROP TRIGGER t1_bi; DROP TABLE t1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i1 INT); +SET @save_sql_mode=@@sql_mode; +SET SQL_MODE=''; +CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW +SET @x = 5/0; +SET SQL_MODE='traditional'; +CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW +SET @x = 5/0; +SET @x=1; +INSERT INTO t1 VALUES (@x); +SELECT @x; +@x +NULL +SET @x=2; +UPDATE t1 SET i1 = @x; +ERROR 22012: Division by 0 +SELECT @x; +@x +2 +SET SQL_MODE=''; +SET @x=3; +INSERT INTO t1 VALUES (@x); +SELECT @x; +@x +NULL +SET @x=4; +UPDATE t1 SET i1 = @x; +ERROR 22012: Division by 0 +SELECT @x; +@x +4 +SET @@sql_mode=@save_sql_mode; +DROP TRIGGER t1_ai; +DROP TRIGGER t1_au; +DROP TABLE t1; +DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +CREATE TABLE t1 (i1 INT); +INSERT INTO t1 VALUES (3); +CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET i1 = 5; +CREATE PROCEDURE p2(INOUT i1 INT) DETERMINISTIC NO SQL SET i1 = i1 * 7; +CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW +BEGIN +CALL p1(NEW.i1); +CALL p2(NEW.i1); +END// +UPDATE t1 SET i1 = 11 WHERE i1 = 3; +DROP TRIGGER t1_bu; +DROP PROCEDURE p2; +DROP PROCEDURE p1; +INSERT INTO t1 VALUES (13); +CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 17; +CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW +CALL p1(OLD.i1); +UPDATE t1 SET i1 = 19 WHERE i1 = 13; +ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger +DROP TRIGGER t1_bu; +DROP PROCEDURE p1; +INSERT INTO t1 VALUES (23); +CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 29; +CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW +CALL p1(OLD.i1); +UPDATE t1 SET i1 = 31 WHERE i1 = 23; +ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger +DROP TRIGGER t1_bu; +DROP PROCEDURE p1; +INSERT INTO t1 VALUES (37); +CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 41; +CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW +CALL p1(NEW.i1); +UPDATE t1 SET i1 = 43 WHERE i1 = 37; +ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger +DROP TRIGGER t1_au; +DROP PROCEDURE p1; +INSERT INTO t1 VALUES (47); +CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 49; +CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW +CALL p1(NEW.i1); +UPDATE t1 SET i1 = 51 WHERE i1 = 47; +ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger +DROP TRIGGER t1_au; +DROP PROCEDURE p1; +SELECT * FROM t1; +i1 +35 +13 +23 +43 +51 +DROP TABLE t1; diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index e941e740fcb..61482ab282c 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -245,22 +245,22 @@ show warnings; Level Code Message desc t1; Field Type Null Key Default Extra -x decimal(21,2) unsigned NO 0.00 +x decimal(21,2) NO 0.00 drop table t1; create table t1 select 0.0 x; desc t1; Field Type Null Key Default Extra -x decimal(2,1) unsigned NO 0.0 +x decimal(2,1) NO 0.0 create table t2 select 105213674794682365.00 y; desc t2; Field Type Null Key Default Extra -y decimal(20,2) unsigned NO 0.00 +y decimal(20,2) NO 0.00 create table t3 select x+y a from t1,t2; show warnings; Level Code Message desc t3; Field Type Null Key Default Extra -a decimal(21,2) unsigned NO 0.00 +a decimal(21,2) NO 0.00 drop table t1,t2,t3; create table t1 (s1 float(0,2)); ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1'). diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 938dccc864c..968c6d3ec6f 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -68,10 +68,10 @@ NULL 1.1 NULL NULL NULL 1 show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `nullif(1.1, 1.1)` decimal(2,1) unsigned default NULL, - `nullif(1.1, 1.2)` decimal(2,1) unsigned default NULL, - `nullif(1.1, 0.11e1)` decimal(2,1) unsigned default NULL, - `nullif(1.0, 1)` decimal(2,1) unsigned default NULL, + `nullif(1.1, 1.1)` decimal(2,1) default NULL, + `nullif(1.1, 1.2)` decimal(2,1) default NULL, + `nullif(1.1, 0.11e1)` decimal(2,1) default NULL, + `nullif(1.0, 1)` decimal(2,1) default NULL, `nullif(1, 1.0)` int(1) default NULL, `nullif(1, 1.1)` int(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 @@ -174,9 +174,9 @@ create table t1 select round(15.4,-1), truncate(-5678.123451,-3), abs(-1.1), -(- show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `round(15.4,-1)` decimal(3,0) unsigned NOT NULL default '0', + `round(15.4,-1)` decimal(3,0) NOT NULL default '0', `truncate(-5678.123451,-3)` decimal(4,0) NOT NULL default '0', - `abs(-1.1)` decimal(2,1) NOT NULL default '0.0', + `abs(-1.1)` decimal(3,1) NOT NULL default '0.0', `-(-1.1)` decimal(2,1) NOT NULL default '0.0' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; @@ -771,7 +771,7 @@ create table t1 as select 0.5; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `0.5` decimal(2,1) unsigned NOT NULL default '0.0' + `0.5` decimal(2,1) NOT NULL default '0.0' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; select round(1.5),round(2.5); diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 70586a3e1e9..8cee60cf49a 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -1,4 +1,31 @@ drop table if exists t1,t2; +set @my_binlog_cache_size =@@global.binlog_cache_size; +set @my_connect_timeout =@@global.connect_timeout; +set @my_delayed_insert_timeout =@@global.delayed_insert_timeout; +set @my_delayed_queue_size =@@global.delayed_queue_size; +set @my_flush =@@global.flush; +set @my_flush_time =@@global.flush_time; +set @my_key_buffer_size =@@global.key_buffer_size; +set @my_max_binlog_cache_size =@@global.max_binlog_cache_size; +set @my_max_binlog_size =@@global.max_binlog_size; +set @my_max_connect_errors =@@global.max_connect_errors; +set @my_max_delayed_threads =@@global.max_delayed_threads; +set @my_max_heap_table_size =@@global.max_heap_table_size; +set @my_max_insert_delayed_threads=@@global.max_insert_delayed_threads; +set @my_max_join_size =@@global.max_join_size; +set @my_max_user_connections =@@global.max_user_connections; +set @my_max_write_lock_count =@@global.max_write_lock_count; +set @my_myisam_data_pointer_size =@@global.myisam_data_pointer_size; +set @my_net_buffer_length =@@global.net_buffer_length; +set @my_net_write_timeout =@@global.net_write_timeout; +set @my_net_read_timeout =@@global.net_read_timeout; +set @my_query_cache_limit =@@global.query_cache_limit; +set @my_query_cache_type =@@global.query_cache_type; +set @my_rpl_recovery_rank =@@global.rpl_recovery_rank; +set @my_server_id =@@global.server_id; +set @my_slow_launch_time =@@global.slow_launch_time; +set @my_storage_engine =@@global.storage_engine; +set @my_thread_cache_size =@@global.thread_cache_size; set @`test`=1; select @test, @`test`, @TEST, @`TEST`, @"teSt"; @test @`test` @TEST @`TEST` @"teSt" @@ -641,3 +668,30 @@ show variables like 'log_queries_not_using_indexes'; Variable_name Value log_queries_not_using_indexes OFF End of 5.0 tests +set global binlog_cache_size =@my_binlog_cache_size; +set global connect_timeout =@my_connect_timeout; +set global delayed_insert_timeout =@my_delayed_insert_timeout; +set global delayed_queue_size =@my_delayed_queue_size; +set global flush =@my_flush; +set global flush_time =@my_flush_time; +set global key_buffer_size =@my_key_buffer_size; +set global max_binlog_cache_size =default; +set global max_binlog_size =@my_max_binlog_size; +set global max_connect_errors =@my_max_connect_errors; +set global max_delayed_threads =@my_max_delayed_threads; +set global max_heap_table_size =@my_max_heap_table_size; +set global max_insert_delayed_threads=@my_max_insert_delayed_threads; +set global max_join_size =@my_max_join_size; +set global max_user_connections =@my_max_user_connections; +set global max_write_lock_count =@my_max_write_lock_count; +set global myisam_data_pointer_size =@my_myisam_data_pointer_size; +set global net_buffer_length =@my_net_buffer_length; +set global net_write_timeout =@my_net_write_timeout; +set global net_read_timeout =@my_net_read_timeout; +set global query_cache_limit =@my_query_cache_limit; +set global query_cache_type =@my_query_cache_type; +set global rpl_recovery_rank =@my_rpl_recovery_rank; +set global server_id =@my_server_id; +set global slow_launch_time =@my_slow_launch_time; +set global storage_engine =@my_storage_engine; +set global thread_cache_size =@my_thread_cache_size; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 667d10cd145..9c991c9c01c 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -706,7 +706,7 @@ create view v1 as select a from t1; create view v2 as select a from t2 where a in (select a from v1); show create view v2; View Create View -v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a` from `t2` where `a` in (select `v1`.`a` AS `a` from `v1`) +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a` from `t2` where `t2`.`a` in (select `v1`.`a` AS `a` from `v1`) drop view v2, v1; drop table t1, t2; CREATE VIEW `v 1` AS select 5 AS `5`; @@ -2649,3 +2649,48 @@ ldt 2006-01-01 03:00:00 drop view v1, v2; drop table t1; +CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, d datetime); +CREATE VIEW v1 AS +SELECT id, date(d) + INTERVAL TIME_TO_SEC(d) SECOND AS t, COUNT(*) +FROM t1 GROUP BY id, t; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`id` AS `id`,(cast(`t1`.`d` as date) + interval time_to_sec(`t1`.`d`) second) AS `t`,count(0) AS `COUNT(*)` from `t1` group by `t1`.`id`,(cast(`t1`.`d` as date) + interval time_to_sec(`t1`.`d`) second) +SELECT * FROM v1; +id t COUNT(*) +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (i INT, j BIGINT); +INSERT INTO t1 VALUES (1, 2), (2, 2), (3, 2); +CREATE VIEW v1 AS SELECT MIN(j) AS j FROM t1; +CREATE VIEW v2 AS SELECT MIN(i) FROM t1 WHERE j = ( SELECT * FROM v1 ); +SELECT * FROM v2; +MIN(i) +1 +DROP VIEW v2, v1; +DROP TABLE t1; +CREATE TABLE t1( +fName varchar(25) NOT NULL, +lName varchar(25) NOT NULL, +DOB date NOT NULL, +uID int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY); +INSERT INTO t1(fName, lName, DOB) VALUES +('Hank', 'Hill', '1964-09-29'), +('Tom', 'Adams', '1908-02-14'), +('Homer', 'Simpson', '1968-03-05'); +CREATE VIEW v1 AS +SELECT (year(now())-year(DOB)) AS Age +FROM t1 HAVING Age < 75; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache (year(now()) - year(`t1`.`DOB`)) AS `Age` from `t1` having (`Age` < 75) +SELECT (year(now())-year(DOB)) AS Age FROM t1 HAVING Age < 75; +Age +42 +38 +SELECT * FROM v1; +Age +42 +38 +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/std_data/untrusted-cacert.pem b/mysql-test/std_data/untrusted-cacert.pem new file mode 100644 index 00000000000..981dd004fc6 --- /dev/null +++ b/mysql-test/std_data/untrusted-cacert.pem @@ -0,0 +1,53 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com + Validity + Not Before: Jan 18 20:12:32 2005 GMT + Not After : Oct 15 20:12:32 2007 GMT + Subject: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (512 bit) + Modulus (512 bit): + 00:cf:2b:14:00:b0:3c:df:6f:9e:91:40:ec:c8:f6: + 90:b2:5b:b4:70:80:a5:a4:0a:73:c7:44:f3:2a:26: + c4:2f:f1:3a:f1:c3:c4:ac:fc:c3:d2:c3:bf:f5:d7: + 6a:38:42:ad:22:ab:c8:c4:4b:4c:1d:16:af:05:34: + 7d:79:97:5e:e1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + CB:0F:1F:E9:A2:76:71:C9:E6:E8:23:A6:C1:18:B7:CC:44:CF:B9:84 + X509v3 Authority Key Identifier: + keyid:CB:0F:1F:E9:A2:76:71:C9:E6:E8:23:A6:C1:18:B7:CC:44:CF:B9:84 + DirName:/C=US/ST=Oregon/L=Portland/O=sawtooth/CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 27:f7:3d:fb:39:6f:73:a4:86:f3:a0:48:22:60:84:e9:5c:3d: + 28:36:05:16:44:98:07:87:e1:5d:b5:f3:a7:bc:33:5f:f4:29: + a9:5f:87:33:df:e6:8e:bd:e2:f3:0a:c8:00:69:ae:3d:41:47: + 03:ea:0b:4c:67:45:4b:ab:f3:39 +-----BEGIN CERTIFICATE----- +MIIC7zCCApmgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBiTELMAkGA1UEBhMCVVMx +DzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxhbmQxETAPBgNVBAoTCHNh +d3Rvb3RoMSQwIgYDVQQDExt3d3cuc2F3dG9vdGgtY29uc3VsdGluZy5jb20xHTAb +BgkqhkiG9w0BCQEWDmluZm9AeWFzc2wuY29tMB4XDTA1MDExODIwMTIzMloXDTA3 +MTAxNTIwMTIzMlowgYkxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIEwZPcmVnb24xETAP +BgNVBAcTCFBvcnRsYW5kMREwDwYDVQQKEwhzYXd0b290aDEkMCIGA1UEAxMbd3d3 +LnNhd3Rvb3RoLWNvbnN1bHRpbmcuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlh +c3NsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDPKxQAsDzfb56RQOzI9pCy +W7RwgKWkCnPHRPMqJsQv8Trxw8Ss/MPSw7/112o4Qq0iq8jES0wdFq8FNH15l17h +AgMBAAGjgekwgeYwHQYDVR0OBBYEFMsPH+midnHJ5ugjpsEYt8xEz7mEMIG2BgNV +HSMEga4wgauAFMsPH+midnHJ5ugjpsEYt8xEz7mEoYGPpIGMMIGJMQswCQYDVQQG +EwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDERMA8GA1UE +ChMIc2F3dG9vdGgxJDAiBgNVBAMTG3d3dy5zYXd0b290aC1jb25zdWx0aW5nLmNv +bTEdMBsGCSqGSIb3DQEJARYOaW5mb0B5YXNzbC5jb22CAQAwDAYDVR0TBAUwAwEB +/zANBgkqhkiG9w0BAQQFAANBACf3Pfs5b3OkhvOgSCJghOlcPSg2BRZEmAeH4V21 +86e8M1/0KalfhzPf5o694vMKyABprj1BRwPqC0xnRUur8zk= +-----END CERTIFICATE----- diff --git a/mysql-test/t/blackhole.test b/mysql-test/t/blackhole.test index e40b84eb5cd..493f74ded3e 100644 --- a/mysql-test/t/blackhole.test +++ b/mysql-test/t/blackhole.test @@ -128,3 +128,15 @@ show binlog events; drop table t1,t2,t3; # End of 4.1 tests + +# +# BUG#10952 - alter table ... lost data without errors and warnings +# +drop table if exists t1; +create table t1 (c char(20)) engine=MyISAM; +insert into t1 values ("Monty"),("WAX"),("Walrus"); +--error 1031 +alter table t1 engine=blackhole; +drop table t1; + +# End of 5.0 tests diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 1b587eea40f..007847fab37 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -11,4 +11,3 @@ ############################################################################## ndb_load : Bug#17233 -udf : Not yet diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test index 45bd0c7a51c..09f07c2852f 100644 --- a/mysql-test/t/distinct.test +++ b/mysql-test/t/distinct.test @@ -382,3 +382,19 @@ INSERT INTO t1 VALUES select count(distinct x,y) from t1; select count(distinct concat(x,y)) from t1; drop table t1; + +# +# Bug #18068: SELECT DISTINCT +# +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a,b)); + +INSERT INTO t1 VALUES (1, 101); +INSERT INTO t1 SELECT a + 1, a + 101 FROM t1; +INSERT INTO t1 SELECT a + 2, a + 102 FROM t1; +INSERT INTO t1 SELECT a + 4, a + 104 FROM t1; +INSERT INTO t1 SELECT a + 8, a + 108 FROM t1; + +EXPLAIN SELECT DISTINCT a,a FROM t1 WHERE b < 12 ORDER BY a; +SELECT DISTINCT a,a FROM t1 WHERE b < 12 ORDER BY a; + +DROP TABLE t1; diff --git a/mysql-test/t/explain.test b/mysql-test/t/explain.test index 2a3a23c5f96..a38771db233 100644 --- a/mysql-test/t/explain.test +++ b/mysql-test/t/explain.test @@ -43,3 +43,12 @@ drop table ÔÁÂ; set names latin1; # End of 4.1 tests + + +# +# Bug#15463: EXPLAIN SELECT..INTO hangs the client (QB, command line) +# +select 3 into @v1; +explain select 3 into @v1; + +# End of 5.0 tests. diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index 351d1fc2c92..8ddf1fbe314 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -220,3 +220,15 @@ set @str=NULL; drop table t2; drop table t1; +# BUG#19618: Crash in range optimizer for +# "unsigned_keypart NOT IN(negative_number,...)" +# (introduced in fix BUG#15872) +create table t1 ( + some_id smallint(5) unsigned, + key (some_id) +); +insert into t1 values (1),(2); +select some_id from t1 where some_id not in(2,-1); +select some_id from t1 where some_id not in(-4,-1,-4); +select some_id from t1 where some_id not in(-4,-1,3423534,2342342); +drop table t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 85cedee0f4a..7f809dbc4a1 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -666,7 +666,14 @@ select rpad(i, 7, ' ') as t from t1; --disable_metadata drop table t1; -# End of 4.1 tests +# +# Bug #10418: LOAD_FILE does not behave like in manual if file does not exist +# + +select load_file("lkjlkj"); +select ifnull(load_file("lkjlkj"),"it's null"); + +--echo End of 4.1 tests # # Bug #13361: SELECT FORMAT(<decimal field with null>, 2) crashes @@ -691,4 +698,10 @@ select cast(rtrim(' 20.06 ') as decimal(19,2)); select cast(ltrim(' 20.06 ') as decimal(19,2)); select cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2)); +# +# Bug #13975: "same string" + 0 has 2 different results +# +select conv("18383815659218730760",10,10) + 0; +select "18383815659218730760" + 0; + --echo End of 5.0 tests diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 4e4fb8f777a..1c7f387e354 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -352,6 +352,20 @@ INSERT INTO t1 VALUES (NOW()); SELECT count(*) FROM t1 WHERE d>FROM_DAYS(TO_DAYS(@TMP)) AND d<=FROM_DAYS(TO_DAYS(@TMP)+1); DROP TABLE t1; +# +# Bug #10568 +# + +select last_day('2005-00-00'); +select last_day('2005-00-01'); +select last_day('2005-01-00'); + +# +# Bug #18501: monthname and NULLs +# + +select monthname(str_to_date(null, '%m')), monthname(str_to_date(null, '%m')), + monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m')); # End of 4.1 tests diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index bff07366ec2..d9836ccc8df 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -782,3 +782,19 @@ SELECT COUNT(DISTINCT a) FROM t1 WHERE a=0; DROP TABLE t1; DROP PROCEDURE a; + +# +# Bug #18068: SELECT DISTINCT +# + +CREATE TABLE t1 (a varchar(64) NOT NULL default '', PRIMARY KEY(a)); + +INSERT INTO t1 (a) VALUES + (''), ('CENTRAL'), ('EASTERN'), ('GREATER LONDON'), + ('NORTH CENTRAL'), ('NORTH EAST'), ('NORTH WEST'), ('SCOTLAND'), + ('SOUTH EAST'), ('SOUTH WEST'), ('WESTERN'); + +EXPLAIN SELECT DISTINCT a,a FROM t1 ORDER BY a; +SELECT DISTINCT a,a FROM t1 ORDER BY a; + +DROP TABLE t1; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 90b0fd95eee..e96f1ef4bbd 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -793,15 +793,6 @@ DROP VIEW v1; DROP FUNCTION func1; DROP FUNCTION func2; -# -# Bug #15851 Unlistable directories yield no info from information_schema -# -create database mysqltest; -create table mysqltest.t1(a int); ---exec chmod -r $MYSQLTEST_VARDIR/master-data/mysqltest -select table_schema from information_schema.tables where table_schema='mysqltest'; ---exec chmod +r $MYSQLTEST_VARDIR/master-data/mysqltest -drop database mysqltest; # # Bug#15307 GROUP_CONCAT() with ORDER BY returns empty set on information_schema @@ -811,3 +802,23 @@ from information_schema.columns where table_schema='information_schema' and (column_type = 'varchar(7)' or column_type = 'varchar(20)') group by column_type order by num; + +# +# Bug#19236 bad COLUMNS.CHARACTER_MAXIMUM_LENGHT and CHARACTER_OCTET_LENGTH +# +create table t1(f1 char(1) not null, f2 char(9) not null) +default character set utf8; +select CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH from +information_schema.columns where table_schema='test' and table_name = 't1'; +drop table t1; + +# +# Bug#18177 any access to INFORMATION_SCHEMA.ROUTINES crashes +# +use mysql; +INSERT INTO `proc` VALUES ('test','','PROCEDURE','','SQL','CONTAINS_SQL', +'NO','DEFINER','','','BEGIN\r\n \r\nEND','root@%','2006-03-02 18:40:03', +'2006-03-02 18:40:03','',''); +select routine_name from information_schema.routines; +delete from proc where name=''; +use test; diff --git a/mysql-test/t/information_schema_chmod.test b/mysql-test/t/information_schema_chmod.test new file mode 100644 index 00000000000..fb850b8e38d --- /dev/null +++ b/mysql-test/t/information_schema_chmod.test @@ -0,0 +1,20 @@ +# +# Due to "Bug#18474 Unlistable directories yield no info from +# information_schema, part2" this test can't be run on Window with our +# current test framework. When "chmod -r" is done within cygwin the +# MySQL Server can still read the directory. +# Manual testing shows the functionalty to skip unlistable directories +# works on windows +# +--source include/not_windows.inc + + +# +# Bug #15851 Unlistable directories yield no info from information_schema +# +create database mysqltest; +create table mysqltest.t1(a int); +--exec chmod -r $MYSQLTEST_VARDIR/master-data/mysqltest +select table_schema from information_schema.tables where table_schema='mysqltest'; +--exec chmod +r $MYSQLTEST_VARDIR/master-data/mysqltest +drop database mysqltest; diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index c194213e0c9..dc4e240750c 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -779,3 +779,47 @@ SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%' OR FALSE; DROP TABLE t1,t2; + +# +# Bug 19396: LEFT OUTER JOIN over views in curly braces +# +--disable_warnings +DROP VIEW IF EXISTS v1,v2; +DROP TABLE IF EXISTS t1,t2; +--enable_warnings + +CREATE TABLE t1 (a int); +CREATE table t2 (b int); +INSERT INTO t1 VALUES (1), (2), (3), (4), (1), (1), (3); +INSERT INTO t2 VALUES (2), (3); + +CREATE VIEW v1 AS SELECT a FROM t1 JOIN t2 ON t1.a=t2.b; +CREATE VIEW v2 AS SELECT b FROM t2 JOIN t1 ON t2.b=t1.a; + +SELECT v1.a, v2. b + FROM v1 LEFT OUTER JOIN v2 ON (v1.a=v2.b) AND (v1.a >= 3) + GROUP BY v1.a; +SELECT v1.a, v2. b + FROM { OJ v1 LEFT OUTER JOIN v2 ON (v1.a=v2.b) AND (v1.a >= 3) } + GROUP BY v1.a; + +DROP VIEW v1,v2; +DROP TABLE t1,t2; + +# +# Bug 19816: LEFT OUTER JOIN with constant ORed predicates in WHERE clause +# + +CREATE TABLE t1 (a int); +CREATE TABLE t2 (b int); +INSERT INTO t1 VALUES (1), (2), (3), (4); +INSERT INTO t2 VALUES (2), (3); + +SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1=1); + +SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1 OR 1); +SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (0 OR 1); +SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1=1 OR 2=2); +SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.b WHERE (1=1 OR 1=0); + +DROP TABLE t1,t2; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 060f1ea167b..7ea14a811ed 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -379,3 +379,15 @@ check table t1, t2; drop table t1, t2, t3; # End of 4.1 tests + +# +# BUG#10952 - alter table ... lost data without errors and warnings +# +drop table if exists t1; +create table t1 (c char(20)) engine=MyISAM; +insert into t1 values ("Monty"),("WAX"),("Walrus"); +--error 1031 +alter table t1 engine=MERGE; +drop table t1; + +# End of 5.0 tests diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index e76553f42e7..ac4c323f51e 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -72,3 +72,11 @@ drop table t1; # --exec $MYSQL -t --default-character-set utf8 test -e "create table t1 (i int, j int not null, k int); insert into t1 values (null, 1, null); select * from t1; describe t1; drop table t1;" +# +# Bug#19564: mysql displays NULL instead of space +# +--exec $MYSQL -t test -e "create table b19564 (i int, s1 char(1)); insert into b19564 values (1, 'x'); insert into b19564 values (2, NULL); insert into b19564 values (3, ' '); select * from b19564 order by i; drop table b19564;" + +--echo End of 5.0 tests + + diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index 28074fba7e4..d74bb1c3a80 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -122,9 +122,22 @@ select HEX(f) from t3; select HEX(f) from t04; select HEX(f) from t4; +# +# BUG#14157: utf8 encoding in binlog without set character_set_client +# +# BUG: +# This test only works on the MySQL-internal rpl machines. +# Needs to be fixed. Problem is that koi8r is not installed +# on many machines. +# +flush logs; +# --exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table if not exists t5 (a int); set names koi8r; create temporary table `ÑÝÉË` (a int); insert into `ÑÝÉË` values (1); insert into t5 select * from `ÑÝÉË`' +# resulted log is client charset insensitive (latin1 not koi8r) as it must be +# --exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000006 | $MYSQL --default-character-set=latin1 +#select * from t5 /* must be (1),(1) */; # clean up drop table t1, t2, t03, t04, t3, t4; -# End of 4.1 tests +# End of 5.0 tests diff --git a/mysql-test/t/ndb_autodiscover3.test b/mysql-test/t/ndb_autodiscover3.test new file mode 100644 index 00000000000..73b4bf8b94f --- /dev/null +++ b/mysql-test/t/ndb_autodiscover3.test @@ -0,0 +1,65 @@ +-- source include/have_ndb.inc +-- source include/have_multi_ndb.inc +-- source include/not_embedded.inc + + +--disable_warnings +drop table if exists t1, t2; +--enable_warnings + +# +# Transaction ongoing while cluster is restarted +# +--connection server1 +create table t1 (a int key) engine=ndbcluster; + +begin; +insert into t1 values (1); + +--exec $NDB_MGM --no-defaults -e "all restart" >> $NDB_TOOLS_OUTPUT +--exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults >> $NDB_TOOLS_OUTPUT + +--error 1297 +insert into t1 values (2); +--error 1296 +commit; + +drop table t1; + +# +# Stale cache after restart -i +# +--connection server1 +create table t2 (a int, b int, primary key(a,b)) engine=ndbcluster; +insert into t2 values (1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,1); +select * from t2 order by a limit 3; + +--exec $NDB_MGM --no-defaults -e "all restart -i" >> $NDB_TOOLS_OUTPUT +--exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults >> $NDB_TOOLS_OUTPUT + +--connection server2 +create table t2 (a int key) engine=ndbcluster; +insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +select * from t2 order by a limit 3; + +# server 1 should have a stale cache, and in this case wrong frm, transaction must be retried +--connection server1 +--error 1015 +select * from t2 order by a limit 3; +select * from t2 order by a limit 3; + +--exec $NDB_MGM --no-defaults -e "all restart -i" >> $NDB_TOOLS_OUTPUT +--exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults >> $NDB_TOOLS_OUTPUT + +--connection server1 +show tables; +create table t2 (a int key) engine=ndbcluster; +insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +select * from t2 order by a limit 3; + +# server 2 should have a stale cache, but with right frm, transaction need not be retried +--connection server2 +select * from t2 order by a limit 3; + +drop table t2; +# End of 4.1 tests diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test index 4cc9113048f..afee381f5b7 100644 --- a/mysql-test/t/openssl_1.test +++ b/mysql-test/t/openssl_1.test @@ -10,8 +10,8 @@ insert into t1 values (5); grant select on test.* to ssl_user1@localhost require SSL; grant select on test.* to ssl_user2@localhost require cipher "DHE-RSA-AES256-SHA"; -grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com"; -grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com"; +grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/emailAddress=abstract.mysql.developer@mysql.com"; +grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/emailAddress=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/emailAddress=abstract.mysql.developer@mysql.com"; flush privileges; connect (con1,localhost,ssl_user1,,,,,SSL); @@ -54,3 +54,41 @@ ssl_user3@localhost, ssl_user4@localhost; drop table t1; # End of 4.1 tests + +# +# Test that we can't open connection to server if we are using +# a different cacert +# +--exec echo "this query should not execute;" > $MYSQLTEST_VARDIR/tmp/test.sql +--error 1 +--exec $MYSQL_TEST --ssl-ca=$MYSQL_TEST_DIR/std_data/untrusted-cacert.pem --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 + +# +# Test that we can't open connection to server if we are using +# a blank ca +# +--error 1 +--exec $MYSQL_TEST --ssl-ca= --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 + +# +# Test that we can't open connection to server if we are using +# a nonexistent ca file +# +--error 1 +--exec $MYSQL_TEST --ssl-ca=nonexisting_file.pem --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 + +# +# Test that we can't open connection to server if we are using +# a blank client-key +# +--error 1 +--exec $MYSQL_TEST --ssl-key= --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 + +# +# Test that we can't open connection to server if we are using +# a blank client-cert +# +--error 1 +--exec $MYSQL_TEST --ssl-cert= --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 + + diff --git a/mysql-test/t/outfile.test b/mysql-test/t/outfile.test index d404a6fff9f..c48e6c9730d 100644 --- a/mysql-test/t/outfile.test +++ b/mysql-test/t/outfile.test @@ -40,7 +40,6 @@ eval select * into dumpfile "../tmp/outfile-test.2" from t1; --error 1086 eval select * into dumpfile "../tmp/outfile-test.3" from t1; enable_query_log; ---error 13,2 select load_file(concat(@tmpdir,"/outfile-test.not-exist")); --exec rm $MYSQLTEST_VARDIR/tmp/outfile-test.1 --exec rm $MYSQLTEST_VARDIR/tmp/outfile-test.2 diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test index 5caecef176e..86e4b6eed0a 100644 --- a/mysql-test/t/rename.test +++ b/mysql-test/t/rename.test @@ -61,9 +61,15 @@ connection con2; sleep 1; show tables; UNLOCK TABLES; -sleep 1; +connection con1; +reap; +connection con2; show tables; drop table t2, t4; +disconnect con2; +disconnect con1; +connection default; + # End of 4.1 tests diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test index facf0d68d2b..81f0e8a0af7 100644 --- a/mysql-test/t/rpl_temporary.test +++ b/mysql-test/t/rpl_temporary.test @@ -163,14 +163,19 @@ drop table t5; # value was set up at the moment of temp table creation # connection con1; -set @session.pseudo_thread_id=100; +set @@session.pseudo_thread_id=100; create temporary table t101 (id int); create temporary table t102 (id int); -set @session.pseudo_thread_id=200; +set @@session.pseudo_thread_id=200; create temporary table t201 (id int); -create temporary table `#not_user_table_prefixed_with_hash_sign_no_harm` (id int); -set @con1_id=connection_id(); -kill @con1_id; +create temporary table `t``201` (id int); +# emulate internal temp table not to come to binlog +create temporary table `#sql_not_user_table202` (id int); +set @@session.pseudo_thread_id=300; +create temporary table t301 (id int); +create temporary table t302 (id int); +create temporary table `#sql_not_user_table303` (id int); +disconnect con1; #now do something to show that slave is ok after DROP temp tables connection master; @@ -184,4 +189,16 @@ select * from t1 /* must be 1 */; connection master; drop table t1; +# +#14157: utf8 encoding in binlog without set character_set_client +# +--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=latin1 test -e 'create table t1 (a int); set names latin1; create temporary table `äöüÄÖÜ` (a int); insert into `äöüÄÖÜ` values (1); insert into t1 select * from `äöüÄÖÜ`' + +sync_slave_with_master; +#connection slave; +select * from t1; + +connection master; +drop table t1; + # End of 5.0 tests diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index e0ecf981fea..c404ea7e58b 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -31,7 +31,7 @@ wait_for_slave_to_stop; select * from t1; --replace_result $MASTER_MYPORT MASTER_MYPORT --replace_column 1 # 9 # 11 # 23 # 33 # -show slave status; +--query_vertical SHOW SLAVE STATUS # this should fail right after start start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; @@ -41,7 +41,7 @@ sleep 2; wait_for_slave_to_stop; --replace_result $MASTER_MYPORT MASTER_MYPORT --replace_column 1 # 9 # 11 # 23 # 33 # -show slave status; +--query_vertical SHOW SLAVE STATUS # try replicate all until second insert to t2; start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746; @@ -50,7 +50,7 @@ wait_for_slave_to_stop; select * from t2; --replace_result $MASTER_MYPORT MASTER_MYPORT --replace_column 1 # 9 # 11 # 23 # 33 # -show slave status; +--query_vertical SHOW SLAVE STATUS # clean up start slave; @@ -67,7 +67,7 @@ wait_for_slave_to_stop; # here the sql slave thread should be stopped --replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004 --replace_column 1 # 9 # 23 # 33 # -show slave status; +--query_vertical SHOW SLAVE STATUS #testing various error conditions --error 1277 diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 8e3c5847846..4b6ae921b9b 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2886,3 +2886,37 @@ SELECT * FROM t1; UPDATE t1 SET i = i - 1; SELECT * FROM t1; DROP TABLE t1; + +# BUG#17379 + +create table t1 (a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t2 (a int, b int, c int, e int, primary key(a,b,c)); +insert into t2 select A.a, B.a, C.a, C.a from t1 A, t1 B, t1 C; +analyze table t2; +select 'In next EXPLAIN, B.rows must be exactly 10:' Z; + +explain select * from t2 A, t2 B where A.a=5 and A.b=5 and A.C<5 + and B.a=5 and B.b=A.e and (B.b =1 or B.b = 3 or B.b=5); +drop table t1, t2; + +# +#Bug #18940: selection of optimal execution plan caused by equality +# propagation (the bug was fixed by the patch for bug #17379) + +CREATE TABLE t1 (a int PRIMARY KEY, b int, INDEX(b)); +INSERT INTO t1 VALUES (1, 3), (9,4), (7,5), (4,5), (6,2), + (3,1), (5,1), (8,9), (2,2), (0,9); + +CREATE TABLE t2 (c int, d int, f int, INDEX(c,f)); +INSERT INTO t2 VALUES + (1,0,0), (1,0,1), (2,0,0), (2,0,1), (3,0,0), (4,0,1), + (5,0,0), (5,0,1), (6,0,0), (0,0,1), (7,0,0), (7,0,1), + (0,0,0), (0,0,1), (8,0,0), (8,0,1), (9,0,0), (9,0,1); + +EXPLAIN +SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6; +EXPLAIN +SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6 AND a > 0; + +DROP TABLE t1, t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 22500bbd280..9995ff5a9ad 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -5774,6 +5774,76 @@ select routine_name,routine_schema from information_schema.routines where # +# BUG#12472/BUG#15137 'CREATE TABLE ... SELECT ... which explicitly or +# implicitly uses stored function gives "Table not locked" error'. +# +--disable_warnings +drop function if exists bug12472| +--enable_warnings +create function bug12472() returns int return (select count(*) from t1)| +# Check case when function is used directly +create table t3 as select bug12472() as i| +show create table t3| +select * from t3| +drop table t3| +# Check case when function is used indirectly through view +create view v1 as select bug12472() as j| +create table t3 as select * from v1| +show create table t3| +select * from t3| +drop table t3| +drop view v1| +drop function bug12472| + + +# +# BUG#18587: Function that accepts and returns TEXT garbles data if longer than +# 766 chars +# + +# Prepare. + +--disable_warnings +DROP FUNCTION IF EXISTS bug18589_f1| +DROP PROCEDURE IF EXISTS bug18589_p1| +DROP PROCEDURE IF EXISTS bug18589_p2| +--enable_warnings + +CREATE FUNCTION bug18589_f1(arg TEXT) RETURNS TEXT +BEGIN + RETURN CONCAT(arg, ""); +END| + +CREATE PROCEDURE bug18589_p1(arg TEXT, OUT ret TEXT) +BEGIN + SET ret = CONCAT(arg, ""); +END| + +CREATE PROCEDURE bug18589_p2(arg TEXT) +BEGIN + DECLARE v TEXT; + CALL bug18589_p1(arg, v); + SELECT v; +END| + +# Test case. + +SELECT bug18589_f1(REPEAT("a", 767))| + +SET @bug18589_v1 = ""| +CALL bug18589_p1(REPEAT("a", 767), @bug18589_v1)| +SELECT @bug18589_v1| + +CALL bug18589_p2(REPEAT("a", 767))| + +# Cleanup. + +DROP FUNCTION bug18589_f1| +DROP PROCEDURE bug18589_p1| +DROP PROCEDURE bug18589_p2| + + +# # BUG#NNNN: New bug synopsis # #--disable_warnings diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 1ef80bdd7ac..3f48b648f40 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -2085,3 +2085,27 @@ create table t2 (a int, b int); insert into t2 values (2, 1), (1, 0); delete from t1 where c <= 1140006215 and (select b from t2 where a = 2) = 1; drop table t1, t2; + +# +# Bug #7549: Missing error message for invalid view selection with subquery +# + +CREATE TABLE t1 (a INT); + +--error 1054 +CREATE VIEW v1 AS SELECT * FROM t1 WHERE no_such_column = ANY (SELECT 1); +--error 1054 +CREATE VIEW v2 AS SELECT * FROM t1 WHERE no_such_column = (SELECT 1); +--error 1054 +SELECT * FROM t1 WHERE no_such_column = ANY (SELECT 1); + +DROP TABLE t1; + +# +# Bug#19077: A nested materialized derived table is used before being populated. +# +create table t1 (i int, j bigint); +insert into t1 values (1, 2), (2, 2), (3, 2); +select * from (select min(i) from t1 where j=(select * from (select min(j) from t1) t2)) t3; +drop table t1; + diff --git a/mysql-test/t/trigger-grant.test b/mysql-test/t/trigger-grant.test index 7a3f7a9fa94..12b929898a8 100644 --- a/mysql-test/t/trigger-grant.test +++ b/mysql-test/t/trigger-grant.test @@ -564,3 +564,176 @@ SELECT @mysqltest_var; DROP USER mysqltest_u1@localhost; DROP DATABASE mysqltest_db1; + + +# +# Test for bug #14635 Accept NEW.x as INOUT parameters to stored +# procedures from within triggers +# +# We require UPDATE privilege when NEW.x passed as OUT parameter, and +# SELECT and UPDATE when NEW.x passed as INOUT parameter. +# +DELETE FROM mysql.user WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.db WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.tables_priv WHERE User LIKE 'mysqltest_%'; +DELETE FROM mysql.columns_priv WHERE User LIKE 'mysqltest_%'; +FLUSH PRIVILEGES; + +--disable_warnings +DROP DATABASE IF EXISTS mysqltest_db1; +--enable_warnings + +CREATE DATABASE mysqltest_db1; +USE mysqltest_db1; + +CREATE TABLE t1 (i1 INT); +CREATE TABLE t2 (i1 INT); + +CREATE USER mysqltest_dfn@localhost; +CREATE USER mysqltest_inv@localhost; + +GRANT EXECUTE, CREATE ROUTINE, SUPER ON *.* TO mysqltest_dfn@localhost; +GRANT INSERT ON mysqltest_db1.* TO mysqltest_inv@localhost; + +connect (definer,localhost,mysqltest_dfn,,mysqltest_db1); +connect (invoker,localhost,mysqltest_inv,,mysqltest_db1); + +connection definer; +CREATE PROCEDURE p1(OUT i INT) DETERMINISTIC NO SQL SET i = 3; +CREATE PROCEDURE p2(INOUT i INT) DETERMINISTIC NO SQL SET i = i * 5; + +# Check that having no privilege won't work. +connection definer; +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW + CALL p1(NEW.i1); +CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW + CALL p2(NEW.i1); + +connection invoker; +--error ER_COLUMNACCESS_DENIED_ERROR +INSERT INTO t1 VALUES (7); +--error ER_COLUMNACCESS_DENIED_ERROR +INSERT INTO t2 VALUES (11); + +connection definer; +DROP TRIGGER t2_bi; +DROP TRIGGER t1_bi; + +# Check that having only SELECT privilege is not enough. +connection default; +GRANT SELECT ON mysqltest_db1.* TO mysqltest_dfn@localhost; + +connection definer; +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW + CALL p1(NEW.i1); +CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW + CALL p2(NEW.i1); + +connection invoker; +--error ER_COLUMNACCESS_DENIED_ERROR +INSERT INTO t1 VALUES (13); +--error ER_COLUMNACCESS_DENIED_ERROR +INSERT INTO t2 VALUES (17); + +connection default; +REVOKE SELECT ON mysqltest_db1.* FROM mysqltest_dfn@localhost; + +connection definer; +DROP TRIGGER t2_bi; +DROP TRIGGER t1_bi; + +# Check that having only UPDATE privilege is enough for OUT parameter, +# but not for INOUT parameter. +connection default; +GRANT UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost; + +connection definer; +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW + CALL p1(NEW.i1); +CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW + CALL p2(NEW.i1); + +connection invoker; +INSERT INTO t1 VALUES (19); +--error ER_COLUMNACCESS_DENIED_ERROR +INSERT INTO t2 VALUES (23); + +connection default; +REVOKE UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost; + +connection definer; +DROP TRIGGER t2_bi; +DROP TRIGGER t1_bi; + +# Check that having SELECT and UPDATE privileges is enough. +connection default; +GRANT SELECT, UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost; + +connection definer; +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW + CALL p1(NEW.i1); +CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW + CALL p2(NEW.i1); + +connection invoker; +INSERT INTO t1 VALUES (29); +INSERT INTO t2 VALUES (31); + +connection default; +REVOKE SELECT, UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost; + +connection definer; +DROP TRIGGER t2_bi; +DROP TRIGGER t1_bi; + +connection default; +DROP PROCEDURE p2; +DROP PROCEDURE p1; + +# Check that late procedure redefining won't open a security hole. +connection default; +GRANT UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost; + +connection definer; +CREATE PROCEDURE p1(OUT i INT) DETERMINISTIC NO SQL SET i = 37; +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW + CALL p1(NEW.i1); + +connection invoker; +INSERT INTO t1 VALUES (41); + +connection definer; +DROP PROCEDURE p1; +CREATE PROCEDURE p1(IN i INT) DETERMINISTIC NO SQL SET @v1 = i + 43; + +connection invoker; +--error ER_COLUMNACCESS_DENIED_ERROR +INSERT INTO t1 VALUES (47); + +connection definer; +DROP PROCEDURE p1; +CREATE PROCEDURE p1(INOUT i INT) DETERMINISTIC NO SQL SET i = i + 51; + +connection invoker; +--error ER_COLUMNACCESS_DENIED_ERROR +INSERT INTO t1 VALUES (53); + +connection default; +DROP PROCEDURE p1; +REVOKE UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost; + +connection definer; +DROP TRIGGER t1_bi; + +# Cleanup. +disconnect definer; +disconnect invoker; +connection default; +DROP USER mysqltest_inv@localhost; +DROP USER mysqltest_dfn@localhost; +DROP TABLE t2; +DROP TABLE t1; +DROP DATABASE mysqltest_db1; +USE test; + +--echo End of 5.0 tests. diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 00c85a650d1..a5bd2ba0b38 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -1165,4 +1165,126 @@ SELECT * FROM t1 WHERE conn_id != trigger_conn_id; DROP TRIGGER t1_bi; DROP TABLE t1; + +# +# Bug#6951: Triggers/Traditional: SET @ result wrong +# +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (i1 INT); + +SET @save_sql_mode=@@sql_mode; + +SET SQL_MODE=''; + +CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW + SET @x = 5/0; + +SET SQL_MODE='traditional'; + +CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW + SET @x = 5/0; + +SET @x=1; +INSERT INTO t1 VALUES (@x); +SELECT @x; + +SET @x=2; +--error 1365 +UPDATE t1 SET i1 = @x; +SELECT @x; + +SET SQL_MODE=''; + +SET @x=3; +INSERT INTO t1 VALUES (@x); +SELECT @x; + +SET @x=4; +--error 1365 +UPDATE t1 SET i1 = @x; +SELECT @x; + +SET @@sql_mode=@save_sql_mode; + +DROP TRIGGER t1_ai; +DROP TRIGGER t1_au; +DROP TABLE t1; + + +# +# Test for bug #14635 Accept NEW.x as INOUT parameters to stored +# procedures from within triggers +# +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +--enable_warnings + +CREATE TABLE t1 (i1 INT); + +# Check that NEW.x pseudo variable is accepted as INOUT and OUT +# parameter to stored routine. +INSERT INTO t1 VALUES (3); +CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET i1 = 5; +CREATE PROCEDURE p2(INOUT i1 INT) DETERMINISTIC NO SQL SET i1 = i1 * 7; +delimiter //; +CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW +BEGIN + CALL p1(NEW.i1); + CALL p2(NEW.i1); +END// +delimiter ;// +UPDATE t1 SET i1 = 11 WHERE i1 = 3; +DROP TRIGGER t1_bu; +DROP PROCEDURE p2; +DROP PROCEDURE p1; + +# Check that OLD.x pseudo variable is not accepted as INOUT and OUT +# parameter to stored routine. +INSERT INTO t1 VALUES (13); +CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 17; +CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW + CALL p1(OLD.i1); +--error ER_SP_NOT_VAR_ARG +UPDATE t1 SET i1 = 19 WHERE i1 = 13; +DROP TRIGGER t1_bu; +DROP PROCEDURE p1; + +INSERT INTO t1 VALUES (23); +CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 29; +CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW + CALL p1(OLD.i1); +--error ER_SP_NOT_VAR_ARG +UPDATE t1 SET i1 = 31 WHERE i1 = 23; +DROP TRIGGER t1_bu; +DROP PROCEDURE p1; + +# Check that NEW.x pseudo variable is read-only in the AFTER TRIGGER. +INSERT INTO t1 VALUES (37); +CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 41; +CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW + CALL p1(NEW.i1); +--error ER_SP_NOT_VAR_ARG +UPDATE t1 SET i1 = 43 WHERE i1 = 37; +DROP TRIGGER t1_au; +DROP PROCEDURE p1; + +INSERT INTO t1 VALUES (47); +CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 49; +CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW + CALL p1(NEW.i1); +--error ER_SP_NOT_VAR_ARG +UPDATE t1 SET i1 = 51 WHERE i1 = 47; +DROP TRIGGER t1_au; +DROP PROCEDURE p1; + +# Post requisite. +SELECT * FROM t1; + +DROP TABLE t1; + # End of 5.0 tests diff --git a/mysql-test/t/variables-master.opt b/mysql-test/t/variables-master.opt deleted file mode 100644 index abd826bc7fa..00000000000 --- a/mysql-test/t/variables-master.opt +++ /dev/null @@ -1 +0,0 @@ ---max_join_size=100 diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 6a271a75e46..be1731e7493 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -5,6 +5,37 @@ drop table if exists t1,t2; --enable_warnings +# +# Bug #19263: variables.test doesn't clean up after itself (I/II -- save) +# +set @my_binlog_cache_size =@@global.binlog_cache_size; +set @my_connect_timeout =@@global.connect_timeout; +set @my_delayed_insert_timeout =@@global.delayed_insert_timeout; +set @my_delayed_queue_size =@@global.delayed_queue_size; +set @my_flush =@@global.flush; +set @my_flush_time =@@global.flush_time; +set @my_key_buffer_size =@@global.key_buffer_size; +set @my_max_binlog_cache_size =@@global.max_binlog_cache_size; +set @my_max_binlog_size =@@global.max_binlog_size; +set @my_max_connect_errors =@@global.max_connect_errors; +set @my_max_delayed_threads =@@global.max_delayed_threads; +set @my_max_heap_table_size =@@global.max_heap_table_size; +set @my_max_insert_delayed_threads=@@global.max_insert_delayed_threads; +set @my_max_join_size =@@global.max_join_size; +set @my_max_user_connections =@@global.max_user_connections; +set @my_max_write_lock_count =@@global.max_write_lock_count; +set @my_myisam_data_pointer_size =@@global.myisam_data_pointer_size; +set @my_net_buffer_length =@@global.net_buffer_length; +set @my_net_write_timeout =@@global.net_write_timeout; +set @my_net_read_timeout =@@global.net_read_timeout; +set @my_query_cache_limit =@@global.query_cache_limit; +set @my_query_cache_type =@@global.query_cache_type; +set @my_rpl_recovery_rank =@@global.rpl_recovery_rank; +set @my_server_id =@@global.server_id; +set @my_slow_launch_time =@@global.slow_launch_time; +set @my_storage_engine =@@global.storage_engine; +set @my_thread_cache_size =@@global.thread_cache_size; + # case insensitivity tests (new in 5.0) set @`test`=1; select @test, @`test`, @TEST, @`TEST`, @"teSt"; @@ -539,3 +570,37 @@ select @@log_queries_not_using_indexes; show variables like 'log_queries_not_using_indexes'; --echo End of 5.0 tests + +# This is at the very after the versioned tests, since it involves doing +# cleanup +# +# Bug #19263: variables.test doesn't clean up after itself (II/II -- +# restore) +# +set global binlog_cache_size =@my_binlog_cache_size; +set global connect_timeout =@my_connect_timeout; +set global delayed_insert_timeout =@my_delayed_insert_timeout; +set global delayed_queue_size =@my_delayed_queue_size; +set global flush =@my_flush; +set global flush_time =@my_flush_time; +set global key_buffer_size =@my_key_buffer_size; +set global max_binlog_cache_size =default; #@my_max_binlog_cache_size; +set global max_binlog_size =@my_max_binlog_size; +set global max_connect_errors =@my_max_connect_errors; +set global max_delayed_threads =@my_max_delayed_threads; +set global max_heap_table_size =@my_max_heap_table_size; +set global max_insert_delayed_threads=@my_max_insert_delayed_threads; +set global max_join_size =@my_max_join_size; +set global max_user_connections =@my_max_user_connections; +set global max_write_lock_count =@my_max_write_lock_count; +set global myisam_data_pointer_size =@my_myisam_data_pointer_size; +set global net_buffer_length =@my_net_buffer_length; +set global net_write_timeout =@my_net_write_timeout; +set global net_read_timeout =@my_net_read_timeout; +set global query_cache_limit =@my_query_cache_limit; +set global query_cache_type =@my_query_cache_type; +set global rpl_recovery_rank =@my_rpl_recovery_rank; +set global server_id =@my_server_id; +set global slow_launch_time =@my_slow_launch_time; +set global storage_engine =@my_storage_engine; +set global thread_cache_size =@my_thread_cache_size; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 8f759c2d43e..f4798317fa1 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2512,3 +2512,58 @@ create view v2 as select convert_tz(dt, 'UTC', 'Europe/Moscow') as ldt from v1; select * from v2; drop view v1, v2; drop table t1; + +# +# Bug #19490: usage of view specified by a query with GROUP BY +# an expression containing non-constant interval + +CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, d datetime); + +CREATE VIEW v1 AS +SELECT id, date(d) + INTERVAL TIME_TO_SEC(d) SECOND AS t, COUNT(*) + FROM t1 GROUP BY id, t; + +SHOW CREATE VIEW v1; +SELECT * FROM v1; + +DROP VIEW v1; +DROP TABLE t1; + +# +# Bug#19077: A nested materialized view is used before being populated. +# +CREATE TABLE t1 (i INT, j BIGINT); +INSERT INTO t1 VALUES (1, 2), (2, 2), (3, 2); +CREATE VIEW v1 AS SELECT MIN(j) AS j FROM t1; +CREATE VIEW v2 AS SELECT MIN(i) FROM t1 WHERE j = ( SELECT * FROM v1 ); +SELECT * FROM v2; +DROP VIEW v2, v1; +DROP TABLE t1; + +# +# Bug #19573: VIEW with HAVING that refers an alias name +# + +CREATE TABLE t1( + fName varchar(25) NOT NULL, + lName varchar(25) NOT NULL, + DOB date NOT NULL, + uID int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY); + +INSERT INTO t1(fName, lName, DOB) VALUES + ('Hank', 'Hill', '1964-09-29'), + ('Tom', 'Adams', '1908-02-14'), + ('Homer', 'Simpson', '1968-03-05'); + +CREATE VIEW v1 AS + SELECT (year(now())-year(DOB)) AS Age + FROM t1 HAVING Age < 75; +SHOW CREATE VIEW v1; + +SELECT (year(now())-year(DOB)) AS Age FROM t1 HAVING Age < 75; +SELECT * FROM v1; + +DROP VIEW v1; +DROP TABLE t1; + + diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 7737810653d..3c2ac1a7ea5 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -11,7 +11,7 @@ fun:calloc fun:_dl_allocate_tls fun:allocate_stack - fun:pthread_create@@GLIBC_2.1 + fun:pthread_create* } { @@ -34,15 +34,6 @@ } { - pthread allocate_dtv memory loss second - Memcheck:Leak - fun:calloc - fun:allocate_dtv - fun:_dl_allocate_tls - fun:pthread_create* -} - -{ pthread memalign memory loss Memcheck:Leak fun:memalign @@ -73,17 +64,6 @@ } { - pthread strstr uninit - Memcheck:Cond - fun:strstr - obj:/lib/tls/libpthread.so.* - obj:/lib/tls/libpthread.so.* - fun:call_init - fun:_dl_init - obj:/lib/ld-*.so -} - -{ pthread errno Memcheck:Leak fun:calloc @@ -152,3 +132,163 @@ obj:*/libz.so.* fun:gzflush } + +# +# Leaks reported in _dl_* internal functions on Linux amd64 / glibc2.3.2. +# + +{ + _dl_start invalid write8 + Memcheck:Addr8 + fun:_dl_start +} + +{ + _dl_start invalid write4 + Memcheck:Addr4 + fun:_dl_start +} + +{ + _dl_start/_dl_setup_hash invalid read8 + Memcheck:Addr8 + fun:_dl_setup_hash + fun:_dl_start +} + +{ + _dl_sysdep_start invalid write8 + Memcheck:Addr8 + fun:_dl_sysdep_start +} + +{ + _dl_init invalid write8 + Memcheck:Addr8 + fun:_dl_init +} + +{ + _dl_init invalid write4 + Memcheck:Addr4 + fun:_dl_init +} + +{ + _dl_init/_dl_init invalid read8 + Memcheck:Addr8 + fun:_dl_debug_initialize + fun:_dl_init +} + +{ + _dl_init/_dl_debug_state invalid read8 + Memcheck:Addr8 + fun:_dl_debug_state + fun:_dl_init +} + +{ + init invalid write8 + Memcheck:Addr8 + fun:init +} + +{ + fixup invalid write8 + Memcheck:Addr8 + fun:fixup +} + +{ + fixup/_dl_lookup_versioned_symbol invalid read8 + Memcheck:Addr8 + fun:_dl_lookup_versioned_symbol + fun:fixup +} + +{ + _dl_runtime_resolve invalid read8 + Memcheck:Addr8 + fun:_dl_runtime_resolve +} + +{ + __libc_start_main invalid write8 + Memcheck:Addr8 + fun:__libc_start_main +} + +{ + __libc_start_main/__sigjmp_save invalid write4 + Memcheck:Addr4 + fun:__sigjmp_save + fun:__libc_start_main +} + +# +# These seem to be libc threading stuff, not related to MySQL code (allocations +# during pthread_exit()). Googling shows other projects also using these +# suppressions. +# +# Note that these all stem from pthread_exit() deeper in the call stack, but +# Valgrind only allows the top four calls in the suppressions. +# + +{ + libc pthread_exit 1 + Memcheck:Leak + fun:malloc + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + libc pthread_exit 2 + Memcheck:Leak + fun:malloc + fun:_dl_map_object + fun:dl_open_worker + fun:_dl_catch_error +} + +{ + libc pthread_exit 3 + Memcheck:Leak + fun:malloc + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error +} + +{ + libc pthread_exit 4 + Memcheck:Leak + fun:calloc + fun:_dl_check_map_versions + fun:dl_open_worker + fun:_dl_catch_error +} + +{ + libc pthread_exit 5 + Memcheck:Leak + fun:calloc + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + + + +# +# This is seen internally in the system libraries on 64-bit RHAS3. +# + +{ + __lll_mutex_unlock_wake uninitialized + Memcheck:Param + futex(utime) + fun:__lll_mutex_unlock_wake +} diff --git a/mysys/my_init.c b/mysys/my_init.c index c2bfdde0ddd..9b8d4db172f 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -196,8 +196,10 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", _CrtDumpMemoryLeaks(); #endif } + + if (!(infoflag & MY_DONT_FREE_DBUG)) + DBUG_END(); /* Must be done before my_thread_end */ #ifdef THREAD - DBUG_POP(); /* Must be done before my_thread_end */ my_thread_end(); my_thread_global_end(); #if defined(SAFE_MUTEX) diff --git a/ndb/include/mgmapi/mgmapi_config_parameters.h b/ndb/include/mgmapi/mgmapi_config_parameters.h index 7c24c5d698d..410c811213b 100644 --- a/ndb/include/mgmapi/mgmapi_config_parameters.h +++ b/ndb/include/mgmapi/mgmapi_config_parameters.h @@ -65,6 +65,7 @@ #define CFG_DB_BACKUP_DATA_BUFFER_MEM 134 #define CFG_DB_BACKUP_LOG_BUFFER_MEM 135 #define CFG_DB_BACKUP_WRITE_SIZE 136 +#define CFG_DB_BACKUP_MAX_WRITE_SIZE 139 #define CFG_LOG_DESTINATION 147 diff --git a/ndb/include/ndbapi/ndb_cluster_connection.hpp b/ndb/include/ndbapi/ndb_cluster_connection.hpp index c96300047d5..fcce53c90a0 100644 --- a/ndb/include/ndbapi/ndb_cluster_connection.hpp +++ b/ndb/include/ndbapi/ndb_cluster_connection.hpp @@ -95,6 +95,7 @@ public: unsigned no_db_nodes(); unsigned node_id(); + unsigned get_connect_count() const; #endif private: diff --git a/ndb/include/util/SocketServer.hpp b/ndb/include/util/SocketServer.hpp index 4c37e63adf0..c21673f932a 100644 --- a/ndb/include/util/SocketServer.hpp +++ b/ndb/include/util/SocketServer.hpp @@ -74,7 +74,7 @@ public: /** * Constructor / Destructor */ - SocketServer(int maxSessions = 32); + SocketServer(unsigned maxSessions = ~(unsigned)0); ~SocketServer(); /** diff --git a/ndb/src/common/transporter/Transporter.cpp b/ndb/src/common/transporter/Transporter.cpp index 377fabe27ab..820aa4cfc18 100644 --- a/ndb/src/common/transporter/Transporter.cpp +++ b/ndb/src/common/transporter/Transporter.cpp @@ -105,10 +105,10 @@ Transporter::connect_server(NDB_SOCKET_TYPE sockfd) { } { - struct sockaddr addr; + struct sockaddr_in addr; SOCKET_SIZE_TYPE addrlen= sizeof(addr); - int r= getpeername(sockfd, &addr, &addrlen); - m_connect_address= ((struct sockaddr_in *)&addr)->sin_addr; + int r= getpeername(sockfd, (struct sockaddr*)&addr, &addrlen); + m_connect_address= (&addr)->sin_addr; } bool res = connect_server_impl(sockfd); @@ -198,10 +198,10 @@ Transporter::connect_client(NDB_SOCKET_TYPE sockfd) { } { - struct sockaddr addr; + struct sockaddr_in addr; SOCKET_SIZE_TYPE addrlen= sizeof(addr); - int r= getpeername(sockfd, &addr, &addrlen); - m_connect_address= ((struct sockaddr_in *)&addr)->sin_addr; + int r= getpeername(sockfd, (struct sockaddr*)&addr, &addrlen); + m_connect_address= (&addr)->sin_addr; } bool res = connect_client_impl(sockfd); diff --git a/ndb/src/common/util/SocketServer.cpp b/ndb/src/common/util/SocketServer.cpp index 481c656b78b..f0af925cf6d 100644 --- a/ndb/src/common/util/SocketServer.cpp +++ b/ndb/src/common/util/SocketServer.cpp @@ -27,7 +27,7 @@ #define DEBUG(x) ndbout << x << endl; -SocketServer::SocketServer(int maxSessions) : +SocketServer::SocketServer(unsigned maxSessions) : m_sessions(10), m_services(5) { @@ -136,7 +136,7 @@ SocketServer::setup(SocketServer::Service * service, } DBUG_PRINT("info",("bound to %u",ntohs(servaddr.sin_port))); - if (listen(sock, m_maxSessions) == -1){ + if (listen(sock, m_maxSessions > 32 ? 32 : m_maxSessions) == -1){ DBUG_PRINT("error",("listen() - %d - %s", errno, strerror(errno))); NDB_CLOSE_SOCKET(sock); diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp index ea4009015cb..f9089355475 100644 --- a/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/ndb/src/kernel/blocks/backup/Backup.cpp @@ -114,15 +114,16 @@ Backup::execREAD_CONFIG_REQ(Signal* signal) Uint32 szDataBuf = (2 * 1024 * 1024); Uint32 szLogBuf = (2 * 1024 * 1024); - Uint32 szWrite = 32768; + Uint32 szWrite = 32768, maxWriteSize = (256 * 1024); ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_DATA_BUFFER_MEM, &szDataBuf); ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_LOG_BUFFER_MEM, &szLogBuf); ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_WRITE_SIZE, &szWrite); + ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_MAX_WRITE_SIZE, &maxWriteSize); c_defaults.m_logBufferSize = szLogBuf; c_defaults.m_dataBufferSize = szDataBuf; c_defaults.m_minWriteSize = szWrite; - c_defaults.m_maxWriteSize = szWrite; + c_defaults.m_maxWriteSize = maxWriteSize; { // Init all tables ArrayList<Table> tables(c_tablePool); diff --git a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp index 31f73e98142..7bd308119fc 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp @@ -190,7 +190,7 @@ Dbtc::Dbtc(const class Configuration & conf): ndb_mgm_get_int_parameter(p, CFG_DB_TRANS_BUFFER_MEM, &transactionBufferMemory); - ndb_mgm_get_int_parameter(p, CFG_DB_NO_UNIQUE_HASH_INDEXES, + ndb_mgm_get_int_parameter(p, CFG_DICT_TABLE, &maxNoOfIndexes); ndb_mgm_get_int_parameter(p, CFG_DB_NO_INDEX_OPS, &maxNoOfConcurrentIndexOperations); diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp index 761f959acdc..f83f21f14d8 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp @@ -1496,6 +1496,7 @@ int Dbtup::interpreterNextLab(Signal* signal, // word read. Thus we set the register to be a 32 bit register. /* ------------------------------------------------------------- */ TregMemBuffer[theRegister] = 0x50; + // arithmetic conversion if big-endian * (Int64*)(TregMemBuffer+theRegister+2) = TregMemBuffer[theRegister+1]; } else if (TnoDataRW == 3) { /* ------------------------------------------------------------- */ @@ -1554,6 +1555,11 @@ int Dbtup::interpreterNextLab(Signal* signal, Tlen = TattrNoOfWords + 1; if (Toptype == ZUPDATE) { if (TattrNoOfWords <= 2) { + if (TattrNoOfWords == 1) { + // arithmetic conversion if big-endian + TdataForUpdate[1] = *(Int64*)&TregMemBuffer[theRegister + 2]; + TdataForUpdate[2] = 0; + } if (TregType == 0) { /* --------------------------------------------------------- */ // Write a NULL value into the attribute diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index f99478a8cea..061360428af 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -695,10 +695,12 @@ ndb_mgm_get_status(NdbMgmHandle handle) Vector<BaseString> split; tmp.split(split, ":"); if(split.size() != 2){ + SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf); return NULL; } if(!(split[0].trim() == "nodes")){ + SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf); return NULL; } @@ -746,6 +748,7 @@ ndb_mgm_get_status(NdbMgmHandle handle) if(i+1 != noOfNodes){ free(state); + SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, "Node count mismatch"); return NULL; } diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp index 817943f5e51..e9093d59494 100644 --- a/ndb/src/mgmsrv/ConfigInfo.cpp +++ b/ndb/src/mgmsrv/ConfigInfo.cpp @@ -1199,7 +1199,19 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { false, ConfigInfo::CI_INT, "32K", - "0", + "2K", + STR_VALUE(MAX_INT_RNIL) }, + + { + CFG_DB_BACKUP_MAX_WRITE_SIZE, + "BackupMaxWriteSize", + DB_TOKEN, + "Max size of filesystem writes made by backup (in bytes)", + ConfigInfo::CI_USED, + false, + ConfigInfo::CI_INT, + "256K", + "2K", STR_VALUE(MAX_INT_RNIL) }, /*************************************************************************** diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index d40eaab7bd5..b713a3908ab 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -2408,6 +2408,7 @@ int MgmtSrvr::abortBackup(Uint32 backupId) { SignalSender ss(theFacade); + ss.lock(); // lock will be released on exit bool next; NodeId nodeId = 0; diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index 555c2082480..d28e0eba5b3 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -468,9 +468,9 @@ MgmApiSession::get_nodeid(Parser_t::Context &, return; } - struct sockaddr addr; + struct sockaddr_in addr; SOCKET_SIZE_TYPE addrlen= sizeof(addr); - int r = getpeername(m_socket, &addr, &addrlen); + int r = getpeername(m_socket, (struct sockaddr*)&addr, &addrlen); if (r != 0 ) { m_output->println(cmd); m_output->println("result: getpeername(%d) failed, err= %d", m_socket, r); @@ -485,7 +485,7 @@ MgmApiSession::get_nodeid(Parser_t::Context &, NDB_TICKS tick= 0; /* only report error on second attempt as not to clog the cluster log */ while (!m_mgmsrv.alloc_node_id(&tmp, (enum ndb_mgm_node_type)nodetype, - &addr, &addrlen, error_code, error_string, + (struct sockaddr*)&addr, &addrlen, error_code, error_string, tick == 0 ? 0 : log_event)) { /* NDB_MGM_ALLOCID_CONFIG_MISMATCH is a non retriable error */ diff --git a/ndb/src/ndbapi/ClusterMgr.cpp b/ndb/src/ndbapi/ClusterMgr.cpp index 42b7c5b115d..fbff57d3168 100644 --- a/ndb/src/ndbapi/ClusterMgr.cpp +++ b/ndb/src/ndbapi/ClusterMgr.cpp @@ -70,6 +70,7 @@ ClusterMgr::ClusterMgr(TransporterFacade & _facade): noOfAliveNodes= 0; noOfConnectedNodes= 0; theClusterMgrThread= 0; + m_connect_count = 0; DBUG_VOID_RETURN; } @@ -469,6 +470,10 @@ ClusterMgr::reportNodeFailed(NodeId nodeId){ theNode.nfCompleteRep = false; if(noOfAliveNodes == 0) { + theFacade.m_globalDictCache.lock(); + theFacade.m_globalDictCache.invalidate_all(); + theFacade.m_globalDictCache.unlock(); + m_connect_count ++; NFCompleteRep rep; for(Uint32 i = 1; i<MAX_NODES; i++){ if(theNodes[i].defined && theNodes[i].nfCompleteRep == false){ diff --git a/ndb/src/ndbapi/ClusterMgr.hpp b/ndb/src/ndbapi/ClusterMgr.hpp index da8f16d6789..1a1e622a889 100644 --- a/ndb/src/ndbapi/ClusterMgr.hpp +++ b/ndb/src/ndbapi/ClusterMgr.hpp @@ -79,6 +79,7 @@ public: Uint32 getNoOfConnectedNodes() const; void hb_received(NodeId); + Uint32 m_connect_count; private: Uint32 noOfAliveNodes; Uint32 noOfConnectedNodes; diff --git a/ndb/src/ndbapi/DictCache.cpp b/ndb/src/ndbapi/DictCache.cpp index 57d9b361522..740f67da2df 100644 --- a/ndb/src/ndbapi/DictCache.cpp +++ b/ndb/src/ndbapi/DictCache.cpp @@ -300,6 +300,42 @@ GlobalDictCache::drop(NdbTableImpl * tab) abort(); } + +unsigned +GlobalDictCache::get_size() +{ + NdbElement_t<Vector<TableVersion> > * curr = m_tableHash.getNext(0); + int sz = 0; + while(curr != 0){ + sz += curr->theData->size(); + curr = m_tableHash.getNext(curr); + } + return sz; +} + +void +GlobalDictCache::invalidate_all() +{ + DBUG_ENTER("GlobalDictCache::invalidate_all"); + NdbElement_t<Vector<TableVersion> > * curr = m_tableHash.getNext(0); + while(curr != 0){ + Vector<TableVersion> * vers = curr->theData; + if (vers->size()) + { + TableVersion * ver = & vers->back(); + ver->m_impl->m_status = NdbDictionary::Object::Invalid; + ver->m_status = DROPPED; + if (ver->m_refCount == 0) + { + delete ver->m_impl; + vers->erase(vers->size() - 1); + } + } + curr = m_tableHash.getNext(curr); + } + DBUG_VOID_RETURN; +} + void GlobalDictCache::release(NdbTableImpl * tab) { diff --git a/ndb/src/ndbapi/DictCache.hpp b/ndb/src/ndbapi/DictCache.hpp index 2df6a139542..6afa7946a8e 100644 --- a/ndb/src/ndbapi/DictCache.hpp +++ b/ndb/src/ndbapi/DictCache.hpp @@ -71,6 +71,9 @@ public: void alter_table_rep(const char * name, Uint32 tableId, Uint32 tableVersion, bool altered); + + unsigned get_size(); + void invalidate_all(); public: enum Status { OK = 0, diff --git a/ndb/src/ndbapi/SignalSender.cpp b/ndb/src/ndbapi/SignalSender.cpp index a29fe68937b..0ecc98f5f29 100644 --- a/ndb/src/ndbapi/SignalSender.cpp +++ b/ndb/src/ndbapi/SignalSender.cpp @@ -75,7 +75,9 @@ SignalSender::SignalSender(TransporterFacade *facade) { m_cond = NdbCondition_Create(); theFacade = facade; + lock(); m_blockNo = theFacade->open(this, execSignal, execNodeStatus); + unlock(); assert(m_blockNo > 0); } diff --git a/ndb/src/ndbapi/TransporterFacade.hpp b/ndb/src/ndbapi/TransporterFacade.hpp index bdd6fb3d05c..48e1c8ed25f 100644 --- a/ndb/src/ndbapi/TransporterFacade.hpp +++ b/ndb/src/ndbapi/TransporterFacade.hpp @@ -271,6 +271,12 @@ TransporterFacade::unlock_mutex() #include "ClusterMgr.hpp" inline +unsigned Ndb_cluster_connection_impl::get_connect_count() const +{ + return TransporterFacade::instance()->theClusterMgr->m_connect_count; +} + +inline bool TransporterFacade::check_send_size(Uint32 node_id, Uint32 send_size) { diff --git a/ndb/src/ndbapi/ndb_cluster_connection.cpp b/ndb/src/ndbapi/ndb_cluster_connection.cpp index 6c3d08d981d..1e53558f179 100644 --- a/ndb/src/ndbapi/ndb_cluster_connection.cpp +++ b/ndb/src/ndbapi/ndb_cluster_connection.cpp @@ -243,6 +243,12 @@ Ndb_cluster_connection::wait_until_ready(int timeout, } while (1); } +unsigned Ndb_cluster_connection::get_connect_count() const +{ + return m_impl.get_connect_count(); +} + + /* diff --git a/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp b/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp index b305b93fec1..a50d3004364 100644 --- a/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp +++ b/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp @@ -49,6 +49,7 @@ class Ndb_cluster_connection_impl : public Ndb_cluster_connection void init_get_next_node(Ndb_cluster_connection_node_iter &iter); Uint32 get_next_node(Ndb_cluster_connection_node_iter &iter); + inline unsigned get_connect_count() const; private: friend class Ndb; friend class NdbImpl; diff --git a/ndb/test/ndbapi/Makefile.am b/ndb/test/ndbapi/Makefile.am index 0533493ba09..7dfa239cb66 100644 --- a/ndb/test/ndbapi/Makefile.am +++ b/ndb/test/ndbapi/Makefile.am @@ -24,6 +24,7 @@ testOIBasic \ testOperations \ testRestartGci \ testScan \ +testInterpreter \ testScanInterpreter \ testScanPerf \ testSystemRestart \ @@ -65,6 +66,7 @@ testOIBasic_SOURCES = testOIBasic.cpp testOperations_SOURCES = testOperations.cpp testRestartGci_SOURCES = testRestartGci.cpp testScan_SOURCES = testScan.cpp ScanFunctions.hpp +testInterpreter_SOURCES = testInterpreter.cpp testScanInterpreter_SOURCES = testScanInterpreter.cpp ScanFilter.hpp ScanInterpretTest.hpp testScanPerf_SOURCES = testScanPerf.cpp testSystemRestart_SOURCES = testSystemRestart.cpp diff --git a/ndb/test/ndbapi/testInterpreter.cpp b/ndb/test/ndbapi/testInterpreter.cpp index 0baba33d2b2..5d930d3d555 100644 --- a/ndb/test/ndbapi/testInterpreter.cpp +++ b/ndb/test/ndbapi/testInterpreter.cpp @@ -79,46 +79,46 @@ int runTestIncValue32(NDBT_Context* ctx, NDBT_Step* step){ Ndb* pNdb = GETNDB(step); - NdbConnection* pTrans = pNdb->startTransaction(); - if (pTrans == NULL){ - ERR(pNdb->getNdbError()); - return NDBT_FAILED; - } - - NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName()); - if (pOp == NULL) { - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - - int check = pOp->interpretedUpdateTuple(); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - - - // Primary keys - Uint32 pkVal = 1; - check = pOp->equal("KOL1", pkVal ); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } - - // Attributes - - // Update column - Uint32 valToIncWith = 1; - check = pOp->incValue("KOL2", valToIncWith); - if( check == -1 ) { - ERR(pTrans->getNdbError()); - pNdb->closeTransaction(pTrans); - return NDBT_FAILED; - } + NdbConnection* pTrans = pNdb->startTransaction(); + if (pTrans == NULL){ + ERR(pNdb->getNdbError()); + return NDBT_FAILED; + } + + NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName()); + if (pOp == NULL) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + int check = pOp->interpretedUpdateTuple(); + if( check == -1 ) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + + // Primary keys + Uint32 pkVal = 1; + check = pOp->equal("KOL1", pkVal ); + if( check == -1 ) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + // Attributes + + // Update column + Uint32 valToIncWith = 1; + check = pOp->incValue("KOL2", valToIncWith); + if( check == -1 ) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } NdbRecAttr* valueRec = pOp->getValue("KOL2"); if( valueRec == NULL ) { @@ -142,6 +142,122 @@ int runTestIncValue32(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int runTestBug19537(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + const NdbDictionary::Table * pTab = ctx->getTab(); + Ndb* pNdb = GETNDB(step); + + if (strcmp(pTab->getName(), "T1") != 0) { + g_err << "runTestBug19537: skip, table != T1" << endl; + return NDBT_OK; + } + + + NdbConnection* pTrans = pNdb->startTransaction(); + if (pTrans == NULL){ + ERR(pNdb->getNdbError()); + return NDBT_FAILED; + } + + NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName()); + if (pOp == NULL) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + if (pOp->interpretedUpdateTuple() == -1) { + ERR(pOp->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + + // Primary keys + const Uint32 pkVal = 1; + if (pOp->equal("KOL1", pkVal) == -1) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + // Load 64-bit constant into register 1 and + // write from register 1 to 32-bit column KOL2 + const Uint64 reg_val = 0x0102030405060708ULL; + + const Uint32* reg_ptr32 = (const Uint32*)®_val; + if (reg_ptr32[0] == 0x05060708 && reg_ptr32[1] == 0x01020304) { + g_err << "runTestBug19537: platform is LITTLE endian" << endl; + } else if (reg_ptr32[0] == 0x01020304 && reg_ptr32[1] == 0x05060708) { + g_err << "runTestBug19537: platform is BIG endian" << endl; + } else { + g_err << "runTestBug19537: impossible platform" + << hex << " [0]=" << reg_ptr32[0] << " [1]=" <<reg_ptr32[1] << endl; + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + if (pOp->load_const_u64(1, reg_val) == -1 || + pOp->write_attr("KOL2", 1) == -1) { + ERR(pOp->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + if (pTrans->execute(Commit) == -1) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + // Read value via a new transaction + + pTrans = pNdb->startTransaction(); + if (pTrans == NULL){ + ERR(pNdb->getNdbError()); + return NDBT_FAILED; + } + + pOp = pTrans->getNdbOperation(pTab->getName()); + if (pOp == NULL) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + Uint32 kol2 = 0x09090909; + if (pOp->readTuple() == -1 || + pOp->equal("KOL1", pkVal) == -1 || + pOp->getValue("KOL2", (char*)&kol2) == 0) { + ERR(pOp->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + if (pTrans->execute(Commit) == -1) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + // Expected conversion as in C - truncate to lower (logical) word + + if (kol2 == 0x01020304) { + g_err << "runTestBug19537: the bug manifests itself !" << endl; + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + if (kol2 != 0x05060708) { + g_err << "runTestBug19537: impossible KOL2 " << hex << kol2 << endl; + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + pNdb->closeTransaction(pTrans); + return NDBT_OK; +} + NDBT_TESTSUITE(testInterpreter); TESTCASE("IncValue32", @@ -156,6 +272,12 @@ TESTCASE("IncValue64", INITIALIZER(runTestIncValue64); FINALIZER(runClearTable); } +TESTCASE("Bug19537", + "Test big-endian write_attr of 32 bit integer\n"){ + INITIALIZER(runLoadTable); + INITIALIZER(runTestBug19537); + FINALIZER(runClearTable); +} #if 0 TESTCASE("MaxTransactions", "Start transactions until no more can be created\n"){ diff --git a/ndb/tools/waiter.cpp b/ndb/tools/waiter.cpp index db90bd8bd90..cb02d5e7c36 100644 --- a/ndb/tools/waiter.cpp +++ b/ndb/tools/waiter.cpp @@ -124,6 +124,12 @@ getStatus(){ ndbout << "status==NULL, retries="<<retries<<endl; MGMERR(handle); retries++; + ndb_mgm_disconnect(handle); + if (ndb_mgm_connect(handle,0,0,1)) { + MGMERR(handle); + g_err << "Reconnect failed" << endl; + break; + } continue; } int count = status->no_of_nodes; diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc index 95f9029f648..90d9d04cd36 100644 --- a/server-tools/instance-manager/manager.cc +++ b/server-tools/instance-manager/manager.cc @@ -35,12 +35,12 @@ #endif -static int create_pid_file(const char *pid_file_name) +int create_pid_file(const char *pid_file_name, int pid) { if (FILE *pid_file= my_fopen(pid_file_name, O_WRONLY | O_CREAT | O_BINARY, MYF(0))) { - fprintf(pid_file, "%d\n", (int) getpid()); + fprintf(pid_file, "%d\n", (int) pid); my_fclose(pid_file, MYF(0)); return 0; } @@ -138,8 +138,13 @@ void manager(const Options &options) if (user_map.load(options.password_file_name)) return; - /* write pid file */ - if (create_pid_file(options.pid_file_name)) + /* write Instance Manager pid file */ + + log_info("IM pid file: '%s'; PID: %d.", + (const char *) options.pid_file_name, + (int) manager_pid); + + if (create_pid_file(options.pid_file_name, manager_pid)) return; sigset_t mask; diff --git a/server-tools/instance-manager/manager.h b/server-tools/instance-manager/manager.h index 12ed6b3b1ff..3ddf292132e 100644 --- a/server-tools/instance-manager/manager.h +++ b/server-tools/instance-manager/manager.h @@ -20,4 +20,6 @@ struct Options; void manager(const Options &options); +int create_pid_file(const char *pid_file_name, int pid); + #endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H diff --git a/server-tools/instance-manager/mysqlmanager.cc b/server-tools/instance-manager/mysqlmanager.cc index d0b2cf2666c..ef714099de7 100644 --- a/server-tools/instance-manager/mysqlmanager.cc +++ b/server-tools/instance-manager/mysqlmanager.cc @@ -338,6 +338,14 @@ spawn: /* Here we return to main, and fall into manager */ break; default: // parent, success + pid= getpid(); /* Get our pid. */ + + log_info("Angel pid file: '%s'; PID: %d.", + (const char *) options.angel_pid_file_name, + (int) pid); + + create_pid_file(Options::angel_pid_file_name, pid); + while (child_status == CHILD_OK && is_terminated == 0) sigsuspend(&zeromask); diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc index e7d366e7457..a98c0e291be 100644 --- a/server-tools/instance-manager/options.cc +++ b/server-tools/instance-manager/options.cc @@ -44,6 +44,7 @@ const char *Options::user= 0; /* No default value */ const char *default_password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME); const char *default_log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME); const char *Options::config_file= QUOTE(DEFAULT_CONFIG_FILE); +const char *Options::angel_pid_file_name= NULL; #endif const char *Options::log_file_name= default_log_file_name; const char *Options::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME); @@ -58,6 +59,9 @@ char **Options::saved_argv= NULL; /* Remember if the config file was forced */ bool Options::is_forced_default_file= 0; +static const char * const ANGEL_PID_FILE_SUFFIX= ".angel.pid"; +static const int ANGEL_PID_FILE_SUFFIX_LEN= strlen(ANGEL_PID_FILE_SUFFIX); + /* List of options, accepted by the instance manager. List must be closed with empty option. @@ -72,6 +76,7 @@ enum options { #ifndef __WIN__ OPT_RUN_AS_SERVICE, OPT_USER, + OPT_ANGEL_PID_FILE, #else OPT_INSTALL_SERVICE, OPT_REMOVE_SERVICE, @@ -94,7 +99,14 @@ static struct my_option my_long_options[] = { "pid-file", OPT_PID_FILE, "Pid file to use.", (gptr *) &Options::pid_file_name, (gptr *) &Options::pid_file_name, - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + +#ifndef __WIN__ + { "angel-pid-file", OPT_ANGEL_PID_FILE, "Pid file for angel process.", + (gptr *) &Options::angel_pid_file_name, + (gptr *) &Options::angel_pid_file_name, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, +#endif { "socket", OPT_SOCKET, "Socket file to use for connection.", (gptr *) &Options::socket_file_name, (gptr *) &Options::socket_file_name, @@ -290,6 +302,46 @@ int Options::load(int argc, char **argv) get_one_option)) != 0) goto err; +#ifndef __WIN__ + if (Options::run_as_service) + { + if (Options::angel_pid_file_name == NULL) + { + /* + Calculate angel pid file on the IM pid file basis: replace the + extension (everything after the last dot) of the pid file basename to + '.angel.pid'. + */ + + char *angel_pid_file_name; + char *base_name_ptr; + char *ext_ptr; + + angel_pid_file_name= (char *) malloc(strlen(Options::pid_file_name) + + ANGEL_PID_FILE_SUFFIX_LEN); + + strcpy(angel_pid_file_name, Options::pid_file_name); + + base_name_ptr= strrchr(angel_pid_file_name, '/'); + + if (!base_name_ptr) + base_name_ptr= angel_pid_file_name + 1; + + ext_ptr= strrchr(base_name_ptr, '.'); + if (ext_ptr) + *ext_ptr= 0; + + strcat(angel_pid_file_name, ANGEL_PID_FILE_SUFFIX); + + Options::angel_pid_file_name= angel_pid_file_name; + } + else + { + Options::angel_pid_file_name= strdup(Options::angel_pid_file_name); + } + } +#endif + return 0; err: @@ -301,6 +353,11 @@ void Options::cleanup() /* free_defaults returns nothing */ if (Options::saved_argv != NULL) free_defaults(Options::saved_argv); + +#ifndef __WIN__ + if (Options::run_as_service) + free((void *) Options::angel_pid_file_name); +#endif } #ifdef __WIN__ diff --git a/server-tools/instance-manager/options.h b/server-tools/instance-manager/options.h index abb094eac93..ad3458869b6 100644 --- a/server-tools/instance-manager/options.h +++ b/server-tools/instance-manager/options.h @@ -35,6 +35,7 @@ struct Options #else static char run_as_service; /* handle_options doesn't support bool */ static const char *user; + static const char *angel_pid_file_name; #endif static bool is_forced_default_file; static const char *log_file_name; diff --git a/sql-common/client.c b/sql-common/client.c index 72745d72b12..26ebc9cc6b0 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1500,6 +1500,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , mysql->options.ssl_ca= strdup_if_not_null(ca); mysql->options.ssl_capath= strdup_if_not_null(capath); mysql->options.ssl_cipher= strdup_if_not_null(cipher); + mysql->options.ssl_verify_server_cert= FALSE; /* Off by default */ #endif /* HAVE_OPENSSL */ DBUG_RETURN(0); } @@ -1514,17 +1515,16 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , static void mysql_ssl_free(MYSQL *mysql __attribute__((unused))) { - struct st_VioSSLConnectorFd *st= - (struct st_VioSSLConnectorFd*) mysql->connector_fd; + struct st_VioSSLFd *ssl_fd= (struct st_VioSSLFd*) mysql->connector_fd; DBUG_ENTER("mysql_ssl_free"); my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); - if (st) - SSL_CTX_free(st->ssl_context); + my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); + if (ssl_fd) + SSL_CTX_free(ssl_fd->ssl_context); my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); mysql->options.ssl_key = 0; mysql->options.ssl_cert = 0; @@ -1556,6 +1556,77 @@ mysql_get_ssl_cipher(MYSQL *mysql) DBUG_RETURN(NULL); } + +/* + Check the server's (subject) Common Name against the + hostname we connected to + + SYNOPSIS + ssl_verify_server_cert() + vio pointer to a SSL connected vio + server_hostname name of the server that we connected to + + RETURN VALUES + 0 Success + 1 Failed to validate server + + */ +static int ssl_verify_server_cert(Vio *vio, const char* server_hostname) +{ + SSL *ssl; + X509 *server_cert; + char *cp1, *cp2; + char buf[256]; + DBUG_ENTER("ssl_verify_server_cert"); + DBUG_PRINT("enter", ("server_hostname: %s", server_hostname)); + + if (!(ssl= (SSL*)vio->ssl_arg)) + { + DBUG_PRINT("error", ("No SSL pointer found")); + DBUG_RETURN(1); + } + + if (!server_hostname) + { + DBUG_PRINT("error", ("No server hostname supplied")); + DBUG_RETURN(1); + } + + if (!(server_cert= SSL_get_peer_certificate(ssl))) + { + DBUG_PRINT("error", ("Could not get server certificate")); + DBUG_RETURN(1); + } + + /* + We already know that the certificate exchanged was valid; the SSL library + handled that. Now we need to verify that the contents of the certificate + are what we expect. + */ + + X509_NAME_oneline(X509_get_subject_name(server_cert), buf, sizeof(buf)); + X509_free (server_cert); + + DBUG_PRINT("info", ("hostname in cert: %s", buf)); + cp1= strstr(buf, "/CN="); + if (cp1) + { + cp1+= 4; /* Skip the "/CN=" that we found */ + /* Search for next / which might be the delimiter for email */ + cp2= strchr(cp1, '/'); + if (cp2) + *cp2= '\0'; + DBUG_PRINT("info", ("Server hostname in cert: %s", cp1)); + if (!strcmp(cp1, server_hostname)) + { + /* Success */ + DBUG_RETURN(0); + } + } + DBUG_PRINT("error", ("SSL certificate validation failure")); + DBUG_RETURN(1); +} + #endif /* HAVE_OPENSSL */ @@ -1589,7 +1660,6 @@ static MYSQL_METHODS client_methods= #endif }; - MYSQL * CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, const char *passwd, const char *db, @@ -2034,37 +2104,52 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, mysql->client_flag=client_flag; #ifdef HAVE_OPENSSL - /* - Oops.. are we careful enough to not send ANY information without - encryption? - */ if (client_flag & CLIENT_SSL) { + /* Do the SSL layering. */ struct st_mysql_options *options= &mysql->options; + struct st_VioSSLFd *ssl_fd; + + /* + Send client_flag, max_packet_size - unencrypted otherwise + the server does not know we want to do SSL + */ if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net)) { set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); goto error; } - /* Do the SSL layering. */ - if (!(mysql->connector_fd= - (gptr) new_VioSSLConnectorFd(options->ssl_key, - options->ssl_cert, - options->ssl_ca, - options->ssl_capath, - options->ssl_cipher))) + + /* Create the VioSSLConnectorFd - init SSL and load certs */ + if (!(ssl_fd= new_VioSSLConnectorFd(options->ssl_key, + options->ssl_cert, + options->ssl_ca, + options->ssl_capath, + options->ssl_cipher))) { set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); goto error; } + mysql->connector_fd= (void*)ssl_fd; + + /* Connect to the server */ DBUG_PRINT("info", ("IO layer change in progress...")); - if (sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd), - mysql->net.vio, (long) (mysql->options.connect_timeout))) + if (sslconnect(ssl_fd, mysql->net.vio, + (long) (mysql->options.connect_timeout))) { set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); goto error; } DBUG_PRINT("info", ("IO layer change done!")); + + /* Verify server cert */ + if (mysql->options.ssl_verify_server_cert && + ssl_verify_server_cert(mysql->net.vio, mysql->host)) + { + set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); + goto error; + } + } #endif /* HAVE_OPENSSL */ @@ -2804,6 +2889,9 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) case MYSQL_OPT_RECONNECT: mysql->reconnect= *(my_bool *) arg; break; + case MYSQL_OPT_SSL_VERIFY_SERVER_CERT: + mysql->options.ssl_verify_server_cert= *(my_bool *) arg; + break; default: DBUG_RETURN(1); } diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 895f022624c..4e977c06180 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -642,7 +642,8 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*) void field_conv(Field *to,Field *from) { - if (to->real_type() == from->real_type()) + if (to->real_type() == from->real_type() && + !(to->type() == FIELD_TYPE_BLOB && to->table->copy_blobs)) { if (to->pack_length() == from->pack_length() && !(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) && diff --git a/sql/ha_blackhole.cc b/sql/ha_blackhole.cc index 2505919af39..7632ed59949 100644 --- a/sql/ha_blackhole.cc +++ b/sql/ha_blackhole.cc @@ -47,7 +47,7 @@ handlerton blackhole_hton= { NULL, /* create_cursor_read_view */ NULL, /* set_cursor_read_view */ NULL, /* close_cursor_read_view */ - HTON_CAN_RECREATE + HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE }; /***************************************************************************** diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 934437e0c91..28cdfd23b6a 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4048,6 +4048,9 @@ ha_innobase::index_prev( mysql_byte* buf) /* in/out: buffer for previous row in MySQL format */ { + statistic_increment(current_thd->status_var.ha_read_prev_count, + &LOCK_status); + return(general_fetch(buf, ROW_SEL_PREV, 0)); } diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 9780f163634..d2fd1a9e28a 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -55,7 +55,7 @@ handlerton myisammrg_hton= { NULL, /* create_cursor_read_view */ NULL, /* set_cursor_read_view */ NULL, /* close_cursor_read_view */ - HTON_CAN_RECREATE + HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE }; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 138e8c72e7a..3d9bd2dbe0f 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -3512,8 +3512,23 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) { m_table= (void *)tab; m_table_version = tab->getObjectVersion(); - if (!(my_errno= build_index_list(ndb, table, ILBP_OPEN))) + if ((my_errno= build_index_list(ndb, table, ILBP_OPEN))) DBUG_RETURN(my_errno); + + const void *data, *pack_data; + uint length, pack_length; + if (readfrm(table->s->path, &data, &length) || + packfrm(data, length, &pack_data, &pack_length) || + pack_length != tab->getFrmLength() || + memcmp(pack_data, tab->getFrmData(), pack_length)) + { + my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR)); + my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR)); + NdbError err= ndb->getNdbError(NDB_INVALID_SCHEMA_OBJECT); + DBUG_RETURN(ndb_to_mysql_error(&err)); + } + my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR)); + my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR)); } m_table_info= tab_info; } diff --git a/sql/handler.h b/sql/handler.h index eee15fc3576..31aac075a5e 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -409,6 +409,7 @@ struct show_table_alias_st { #define HTON_ALTER_NOT_SUPPORTED (1 << 1) //Engine does not support alter #define HTON_CAN_RECREATE (1 << 2) //Delete all is used fro truncate #define HTON_HIDDEN (1 << 3) //Engine does not appear in lists +#define HTON_ALTER_CANNOT_CREATE (1 << 4) //Cannot use alter to create typedef struct st_thd_trans { diff --git a/sql/item.cc b/sql/item.cc index 31fbef0f053..24efc1f106f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -304,6 +304,7 @@ Item::Item(): marker= 0; maybe_null=null_value=with_sum_func=unsigned_flag=0; decimals= 0; max_length= 0; + with_subselect= 0; /* Put item in free list so that we can free all items at end */ THD *thd= current_thd; @@ -958,6 +959,12 @@ void Item_splocal::print(String *str) } +bool Item_splocal::set_value(THD *thd, sp_rcontext *ctx, Item **it) +{ + return ctx->set_variable(thd, get_var_idx(), it); +} + + /***************************************************************************** Item_case_expr methods *****************************************************************************/ @@ -1883,7 +1890,6 @@ Item_decimal::Item_decimal(const char *str_arg, uint length, name= (char*) str_arg; decimals= (uint8) decimal_value.frac; fixed= 1; - unsigned_flag= !decimal_value.sign(); max_length= my_decimal_precision_to_length(decimal_value.intg + decimals, decimals, unsigned_flag); } @@ -1893,7 +1899,6 @@ Item_decimal::Item_decimal(longlong val, bool unsig) int2my_decimal(E_DEC_FATAL_ERROR, val, unsig, &decimal_value); decimals= (uint8) decimal_value.frac; fixed= 1; - unsigned_flag= !decimal_value.sign(); max_length= my_decimal_precision_to_length(decimal_value.intg + decimals, decimals, unsigned_flag); } @@ -1904,7 +1909,6 @@ Item_decimal::Item_decimal(double val, int precision, int scale) double2my_decimal(E_DEC_FATAL_ERROR, val, &decimal_value); decimals= (uint8) decimal_value.frac; fixed= 1; - unsigned_flag= !decimal_value.sign(); max_length= my_decimal_precision_to_length(decimal_value.intg + decimals, decimals, unsigned_flag); } @@ -1917,7 +1921,6 @@ Item_decimal::Item_decimal(const char *str, const my_decimal *val_arg, name= (char*) str; decimals= (uint8) decimal_par; max_length= length; - unsigned_flag= !decimal_value.sign(); fixed= 1; } @@ -1927,7 +1930,6 @@ Item_decimal::Item_decimal(my_decimal *value_par) my_decimal2decimal(value_par, &decimal_value); decimals= (uint8) decimal_value.frac; fixed= 1; - unsigned_flag= !decimal_value.sign(); max_length= my_decimal_precision_to_length(decimal_value.intg + decimals, decimals, unsigned_flag); } @@ -1939,7 +1941,6 @@ Item_decimal::Item_decimal(const char *bin, int precision, int scale) &decimal_value, precision, scale); decimals= (uint8) decimal_value.frac; fixed= 1; - unsigned_flag= !decimal_value.sign(); max_length= my_decimal_precision_to_length(precision, decimals, unsigned_flag); } @@ -4840,7 +4841,16 @@ void Item_ref::cleanup() void Item_ref::print(String *str) { if (ref) - (*ref)->print(str); + { + if ((*ref)->type() != Item::CACHE_ITEM && ref_type() != VIEW_REF && + name && alias_name_used) + { + THD *thd= current_thd; + append_identifier(thd, str, name, (uint) strlen(name)); + } + else + (*ref)->print(str); + } else Item_ident::print(str); } @@ -5365,6 +5375,25 @@ bool Item_trigger_field::eq(const Item *item, bool binary_cmp) const } +void Item_trigger_field::set_required_privilege(bool rw) +{ + /* + Require SELECT and UPDATE privilege if this field will be read and + set, and only UPDATE privilege for setting the field. + */ + want_privilege= (rw ? SELECT_ACL | UPDATE_ACL : UPDATE_ACL); +} + + +bool Item_trigger_field::set_value(THD *thd, sp_rcontext */*ctx*/, Item **it) +{ + Item *item= sp_prepare_func_item(thd, it); + + return (!item || (!fixed && fix_fields(thd, 0)) || + (item->save_in_field(field, 0) < 0)); +} + + bool Item_trigger_field::fix_fields(THD *thd, Item **items) { /* @@ -5387,8 +5416,7 @@ bool Item_trigger_field::fix_fields(THD *thd, Item **items) if (table_grants) { - table_grants->want_privilege= - access_type == AT_READ ? SELECT_ACL : UPDATE_ACL; + table_grants->want_privilege= want_privilege; if (check_grant_column(thd, table_grants, triggers->table->s->db, triggers->table->s->table_name, field_name, @@ -5420,6 +5448,7 @@ void Item_trigger_field::print(String *str) void Item_trigger_field::cleanup() { + want_privilege= original_privilege; /* Since special nature of Item_trigger_field we should not do most of things from Item_field::cleanup() or Item_ident::cleanup() here. diff --git a/sql/item.h b/sql/item.h index 24aca4a86d1..28b1f54add7 100644 --- a/sql/item.h +++ b/sql/item.h @@ -372,6 +372,42 @@ public: /*************************************************************************/ +class sp_rcontext; + + +class Settable_routine_parameter +{ +public: + /* + Set required privileges for accessing the parameter. + + SYNOPSIS + set_required_privilege() + rw if 'rw' is true then we are going to read and set the + parameter, so SELECT and UPDATE privileges might be + required, otherwise we only reading it and SELECT + privilege might be required. + */ + virtual void set_required_privilege(bool rw) {}; + + /* + Set parameter value. + + SYNOPSIS + set_value() + thd thread handle + ctx context to which parameter belongs (if it is local + variable). + it item which represents new value + + RETURN + FALSE if parameter value has been set, + TRUE if error has occured. + */ + virtual bool set_value(THD *thd, sp_rcontext *ctx, Item **it)= 0; +}; + + typedef bool (Item::*Item_processor)(byte *arg); typedef Item* (Item::*Item_transformer) (byte *arg); typedef void (*Cond_traverser) (const Item *item, void *arg); @@ -424,6 +460,9 @@ public: my_bool is_autogenerated_name; /* indicate was name of this Item autogenerated or set by user */ DTCollation collation; + my_bool with_subselect; /* If this item is a subselect or some + of its arguments is or contains a + subselect */ // alloc & destruct is done as start of select using sql_alloc Item(); @@ -744,6 +783,15 @@ public: } virtual bool is_splocal() { return 0; } /* Needed for error checking */ + + /* + Return Settable_routine_parameter interface of the Item. Return 0 + if this Item is not Settable_routine_parameter. + */ + virtual Settable_routine_parameter *get_settable_routine_parameter() + { + return 0; + } }; @@ -842,7 +890,8 @@ inline bool Item_sp_variable::send(Protocol *protocol, String *str) runtime. *****************************************************************************/ -class Item_splocal :public Item_sp_variable +class Item_splocal :public Item_sp_variable, + private Settable_routine_parameter { uint m_var_idx; @@ -880,6 +929,15 @@ public: inline enum Type type() const; inline Item_result result_type() const; + +private: + bool set_value(THD *thd, sp_rcontext *ctx, Item **it); + +public: + Settable_routine_parameter *get_settable_routine_parameter() + { + return this; + } }; /***************************************************************************** @@ -2100,14 +2158,13 @@ class Table_triggers_list; two Field instances representing either OLD or NEW version of this field. */ -class Item_trigger_field : public Item_field +class Item_trigger_field : public Item_field, + private Settable_routine_parameter { public: /* Is this item represents row from NEW or OLD row ? */ enum row_version_type {OLD_ROW, NEW_ROW}; row_version_type row_version; - /* Is this item used for reading or updating the value? */ - enum access_types { AT_READ = 0x1, AT_UPDATE = 0x2 }; /* Next in list of all Item_trigger_field's in trigger */ Item_trigger_field *next_trg_field; /* Index of the field in the TABLE::field array */ @@ -2118,11 +2175,11 @@ public: Item_trigger_field(Name_resolution_context *context_arg, row_version_type row_ver_arg, const char *field_name_arg, - access_types access_type_arg) + ulong priv, const bool ro) :Item_field(context_arg, (const char *)NULL, (const char *)NULL, field_name_arg), - row_version(row_ver_arg), field_idx((uint)-1), - access_type(access_type_arg), table_grants(NULL) + row_version(row_ver_arg), field_idx((uint)-1), original_privilege(priv), + want_privilege(priv), table_grants(NULL), read_only (ro) {} void setup_field(THD *thd, TABLE *table, GRANT_INFO *table_grant_info); enum Type type() const { return TRIGGER_FIELD_ITEM; } @@ -2133,8 +2190,39 @@ public: void cleanup(); private: - access_types access_type; + void set_required_privilege(bool rw); + bool set_value(THD *thd, sp_rcontext *ctx, Item **it); + +public: + Settable_routine_parameter *get_settable_routine_parameter() + { + return (read_only ? 0 : this); + } + + bool set_value(THD *thd, Item **it) + { + return set_value(thd, NULL, it); + } + +private: + /* + 'want_privilege' holds privileges required to perform operation on + this trigger field (SELECT_ACL if we are going to read it and + UPDATE_ACL if we are going to update it). It is initialized at + parse time but can be updated later if this trigger field is used + as OUT or INOUT parameter of stored routine (in this case + set_required_privilege() is called to appropriately update + want_privilege and cleanup() is responsible for restoring of + original want_privilege once parameter's value is updated). + */ + ulong original_privilege; + ulong want_privilege; GRANT_INFO *table_grants; + /* + Trigger field is read-only unless it belongs to the NEW row in a + BEFORE INSERT of BEFORE UPDATE trigger. + */ + bool read_only; }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 54e281a1f14..725be547a8a 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -204,10 +204,28 @@ longlong Item_func_nop_all::val_int() /* - Convert a constant expression or string to an integer. - This is done when comparing DATE's of different formats and - also when comparing bigint to strings (in which case the string - is converted once to a bigint). + Convert a constant item to an int and replace the original item + + SYNOPSIS + convert_constant_item() + thd thread handle + field item will be converted using the type of this field + item [in/out] reference to the item to convert + + DESCRIPTION + The function converts a constant expression or string to an integer. + On successful conversion the original item is substituted for the + result of the item evaluation. + This is done when comparing DATE/TIME of different formats and + also when comparing bigint to strings (in which case strings + are converted to bigints). + + NOTES + This function is called only at prepare stage. + As all derived tables are filled only after all derived tables + are prepared we do not evaluate items with subselects here because + they can contain derived tables and thus we may attempt to use a + table that has not been populated yet. RESULT VALUES 0 Can't convert item @@ -216,7 +234,7 @@ longlong Item_func_nop_all::val_int() static bool convert_constant_item(THD *thd, Field *field, Item **item) { - if ((*item)->const_item()) + if (!(*item)->with_subselect && (*item)->const_item()) { /* For comparison purposes allow invalid dates like 2000-01-32 */ ulong orig_sql_mode= field->table->in_use->variables.sql_mode; @@ -2570,7 +2588,9 @@ Item_cond::fix_fields(THD *thd, Item **ref) (item= *li.ref())->check_cols(1)) return TRUE; /* purecov: inspected */ used_tables_cache|= item->used_tables(); - if (!item->const_item()) + if (item->const_item()) + and_tables_cache= (table_map) 0; + else { tmp_table_map= item->not_null_tables(); not_null_tables_cache|= tmp_table_map; @@ -2578,6 +2598,7 @@ Item_cond::fix_fields(THD *thd, Item **ref) const_item_cache= FALSE; } with_sum_func= with_sum_func || item->with_sum_func; + with_subselect|= item->with_subselect; if (item->maybe_null) maybe_null=1; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 21aa7ed2a1b..2c770bec1ad 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -184,6 +184,7 @@ Item_func::fix_fields(THD *thd, Item **ref) used_tables_cache|= item->used_tables(); not_null_tables_cache|= item->not_null_tables(); const_item_cache&= item->const_item(); + with_subselect|= item->with_subselect; } } fix_length_and_dec(); @@ -2734,9 +2735,10 @@ String *udf_handler::val_str(String *str,String *save_str) { uchar is_null_tmp=0; ulong res_length; + DBUG_ENTER("udf_handler::val_str"); if (get_arguments()) - return 0; + DBUG_RETURN(0); char * (*func)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *)= (char* (*)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *)) u_d->func; @@ -2746,22 +2748,26 @@ String *udf_handler::val_str(String *str,String *save_str) if (str->alloc(MAX_FIELD_WIDTH)) { error=1; - return 0; + DBUG_RETURN(0); } } char *res=func(&initid, &f_args, (char*) str->ptr(), &res_length, &is_null_tmp, &error); + DBUG_PRINT("info", ("udf func returned, res_length: %lu", res_length)); if (is_null_tmp || !res || error) // The !res is for safety { - return 0; + DBUG_PRINT("info", ("Null or error")); + DBUG_RETURN(0); } if (res == str->ptr()) { str->length(res_length); - return str; + DBUG_PRINT("exit", ("str: %s", str->ptr())); + DBUG_RETURN(str); } save_str->set(res, res_length, str->charset()); - return save_str; + DBUG_PRINT("exit", ("save_str: %s", save_str->ptr())); + DBUG_RETURN(save_str); } @@ -4115,6 +4121,18 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const } +bool Item_func_get_user_var::set_value(THD *thd, + sp_rcontext */*ctx*/, Item **it) +{ + Item_func_set_user_var *suv= new Item_func_set_user_var(get_name(), *it); + /* + Item_func_set_user_var is not fixed after construction, call + fix_fields(). + */ + return (!suv || suv->fix_fields(thd, it) || suv->check() || suv->update()); +} + + bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); @@ -4747,6 +4765,7 @@ Item_func_sp::sp_result_field(void) const dummy_table->alias = empty_name; dummy_table->maybe_null = maybe_null; dummy_table->in_use= current_thd; + dummy_table->copy_blobs= TRUE; share->table_cache_key = empty_name; share->table_name = empty_name; } diff --git a/sql/item_func.h b/sql/item_func.h index a91d93be8c6..1d8a1bd5e22 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1179,7 +1179,8 @@ public: }; -class Item_func_get_user_var :public Item_func +class Item_func_get_user_var :public Item_func, + private Settable_routine_parameter { user_var_entry *var_entry; @@ -1206,6 +1207,15 @@ public: table_map used_tables() const { return const_item() ? 0 : RAND_TABLE_BIT; } bool eq(const Item *item, bool binary_cmp) const; + +private: + bool set_value(THD *thd, sp_rcontext *ctx, Item **it); + +public: + Settable_routine_parameter *get_settable_routine_parameter() + { + return this; + } }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index a1743aa1181..ce9897afeed 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2579,7 +2579,7 @@ String *Item_load_file::val_str(String *str) (void) fn_format(path, file_name->c_ptr(), mysql_real_data_home, "", MY_RELATIVE_PATH | MY_UNPACK_FILENAME); - if (!my_stat(path, &stat_info, MYF(MY_WME))) + if (!my_stat(path, &stat_info, MYF(0))) goto err; if (!(stat_info.st_mode & S_IROTH)) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 7d7b62df0dc..90d421a2c68 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -542,7 +542,7 @@ public: void fix_length_and_dec() { collation.set(default_charset()); - decimals=0; max_length=64; + max_length= 64; } }; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index d93f6501ebb..87ef0fc080e 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -39,6 +39,7 @@ Item_subselect::Item_subselect(): engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0), const_item_cache(1), engine_changed(0), changed(0) { + with_subselect= 1; reset(); /* item value is NULL if select_subselect not changed this value @@ -1351,6 +1352,17 @@ void Item_in_subselect::print(String *str) } +bool Item_in_subselect::fix_fields(THD *thd, Item **ref) +{ + bool result = 0; + + if(thd->lex->view_prepare_mode && left_expr && !left_expr->fixed) + result = left_expr->fix_fields(thd, &left_expr); + + return result || Item_subselect::fix_fields(thd, ref); +} + + Item_subselect::trans_res Item_allany_subselect::select_transformer(JOIN *join) { diff --git a/sql/item_subselect.h b/sql/item_subselect.h index a4dac5bda87..293408dc09e 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -258,6 +258,7 @@ public: void top_level_item() { abort_on_null=1; } bool test_limit(st_select_lex_unit *unit); void print(String *str); + bool fix_fields(THD *thd, Item **ref); friend class Item_ref_null_helper; friend class Item_is_not_null_test; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index d2fef647fb9..72c53272e0c 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -917,9 +917,9 @@ String* Item_func_monthname::val_str(String* str) { DBUG_ASSERT(fixed == 1); const char *month_name; - uint month=(uint) Item_func_month::val_int(); + uint month= (uint) val_int(); - if (!month) // This is also true for NULL + if (null_value || !month) { null_value=1; return (String*) 0; @@ -2144,8 +2144,13 @@ bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const Item_date_add_interval *other= (Item_date_add_interval*) item; if ((int_type != other->int_type) || - (!args[0]->eq(other->args[0], binary_cmp)) || - (get_interval_value(args[1], int_type, &val, &interval))) + (!args[0]->eq(other->args[0], binary_cmp))) + return FALSE; + + if (!args[1]->const_item() || !other->args[1]->const_item()) + return (args[1]->eq(other->args[1], binary_cmp)); + + if (get_interval_value(args[1], int_type, &val, &interval)) return FALSE; val= other->value; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 399b861e8f4..707a474b754 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -718,12 +718,6 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name, List<create_field> &fields, List<Key> &keys, bool tmp_table, uint select_field_count); -TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, - TABLE_LIST *create_table, - List<create_field> *extra_fields, - List<Key> *keys, - List<Item> *items, - MYSQL_LOCK **lock); bool mysql_alter_table(THD *thd, char *new_db, char *new_name, HA_CREATE_INFO *create_info, TABLE_LIST *table_list, @@ -1311,15 +1305,16 @@ extern pthread_t signal_thread; #endif #ifdef HAVE_OPENSSL -extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd; +extern struct st_VioSSLFd * ssl_acceptor_fd; #endif /* HAVE_OPENSSL */ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count, uint flags, bool *need_reopen); -/* mysql_lock_tables() flags bits */ +/* mysql_lock_tables() and open_table() flags bits */ #define MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK 0x0001 #define MYSQL_LOCK_IGNORE_FLUSH 0x0002 #define MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN 0x0004 +#define MYSQL_OPEN_IGNORE_LOCKED_TABLES 0x0008 void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock); void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock); @@ -1583,6 +1578,16 @@ inline int hexchar_to_int(char c) return -1; } +/* + is_user_table() + return true if the table was created explicitly +*/ + +inline bool is_user_table(TABLE * table) +{ + const char *name= table->s->table_name; + return strncmp(name, tmp_file_prefix, tmp_file_prefix_length); +} /* Some functions that are different in the embedded library and the normal diff --git a/sql/mysqld.cc b/sql/mysqld.cc index aa58617ee09..50f19c15fc4 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -621,7 +621,7 @@ static void openssl_lock(int, openssl_lock_t *, const char *, int); static unsigned long openssl_id_function(); #endif char *des_key_file; -struct st_VioSSLAcceptorFd *ssl_acceptor_fd; +struct st_VioSSLFd *ssl_acceptor_fd; #endif /* HAVE_OPENSSL */ @@ -955,7 +955,8 @@ static void __cdecl kill_server(int sig_ptr) RETURN_FROM_KILL_SERVER; kill_in_progress=TRUE; abort_loop=1; // This should be set - my_sigset(sig,SIG_IGN); + if (sig != 0) // 0 is not a valid signal number + my_sigset(sig,SIG_IGN); if (sig == MYSQL_KILL_SIGNAL || sig == 0) sql_print_information(ER(ER_NORMAL_SHUTDOWN),my_progname); else @@ -987,6 +988,10 @@ static void __cdecl kill_server(int sig_ptr) pthread_join(select_thread, NULL); // wait for main thread #endif /* __NETWARE__ */ +#if defined(__NETWARE__) || (defined(USE_ONE_SIGNAL_HAND) && !defined(__WIN__) && !defined(OS2)) + my_thread_end(); +#endif + pthread_exit(0); /* purecov: deadcode */ #endif /* EMBEDDED_LIBRARY */ @@ -1132,8 +1137,13 @@ void clean_up(bool print_message) #endif #ifdef HAVE_OPENSSL if (ssl_acceptor_fd) - my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR)); + { + SSL_CTX_free(ssl_acceptor_fd->ssl_context); + my_free((gptr) ssl_acceptor_fd, MYF(0)); + } #endif /* HAVE_OPENSSL */ + vio_end(); + #ifdef USE_REGEX my_regex_end(); #endif diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 2610e4fc1c8..e36932cbc0c 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -347,8 +347,10 @@ typedef struct st_qsel_param { uint *imerge_cost_buff; /* buffer for index_merge cost estimates */ uint imerge_cost_buff_size; /* size of the buffer */ - /* TRUE if last checked tree->key can be used for ROR-scan */ + /* TRUE if last checked tree->key can be used for ROR-scan */ bool is_ror_scan; + /* Number of ranges in the last checked tree->key */ + uint n_ranges; } PARAM; class TABLE_READ_PLAN; @@ -3501,17 +3503,46 @@ static SEL_TREE *get_func_mm_tree(PARAM *param, Item_func *cond_func, if (inv) { - /* - We get here for conditions like "t.keypart NOT IN (....)". - - If the IN-list contains only constants (and func->array is an ordered - array of them), we construct the appropriate SEL_ARG tree manually, - because constructing it using the range analyzer (as - AND_i( t.keypart != c_i)) will cause lots of memory to be consumed - (see BUG#15872). - */ if (func->array && func->cmp_type != ROW_RESULT) { + /* + We get here for conditions in form "t.key NOT IN (c1, c2, ...)" + (where c{i} are constants). + Our goal is to produce a SEL_ARG graph that represents intervals: + + ($MIN<t.key<c1) OR (c1<t.key<c2) OR (c2<t.key<c3) OR ... (*) + + where $MIN is either "-inf" or NULL. + + The most straightforward way to handle NOT IN would be to convert + it to "(t.key != c1) AND (t.key != c2) AND ..." and let the range + optimizer to build SEL_ARG graph from that. However that will cause + the range optimizer to use O(N^2) memory (it's a bug, not filed), + and people do use big NOT IN lists (see BUG#15872). Also, for big + NOT IN lists constructing/using graph (*) does not make the query + faster. + + So, we will handle NOT IN manually in the following way: + * if the number of entries in the NOT IN list is less then + NOT_IN_IGNORE_THRESHOLD, we will construct SEL_ARG graph (*) + manually. + * Otherwise, we will construct a smaller graph: for + "t.key NOT IN (c1,...cN)" we construct a graph representing + ($MIN < t.key) OR (cN < t.key) // here sequence of c_i is + // ordered. + + A note about partially-covering indexes: for those (e.g. for + "a CHAR(10), KEY(a(5))") the handling is correct (albeit not very + efficient): + Instead of "t.key < c1" we get "t.key <= prefix-val(c1)". + Combining the intervals in (*) together, we get: + (-inf<=t.key<=c1) OR (c1<=t.key<=c2) OR (c2<=t.key<=c3) OR ... + i.e. actually we get intervals combined into one interval: + (-inf<=t.key<=+inf). This doesn't make much sense but it doesn't + cause any problems. + */ + MEM_ROOT *tmp_root= param->mem_root; + param->thd->mem_root= param->old_root; /* Create one Item_type constant object. We'll need it as get_mm_parts only accepts constant values wrapped in Item_Type @@ -3520,25 +3551,35 @@ static SEL_TREE *get_func_mm_tree(PARAM *param, Item_func *cond_func, per-statement mem_root (while thd->mem_root is currently pointing to mem_root local to range optimizer). */ - MEM_ROOT *tmp_root= param->mem_root; - param->thd->mem_root= param->old_root; Item *value_item= func->array->create_item(); param->thd->mem_root= tmp_root; if (!value_item) break; - /* Get a SEL_TREE for "-inf < X < c_0" interval */ - func->array->value_to_item(0, value_item); - tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC, - value_item, cmp_type); - if (!tree) + /* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval. */ + uint i=0; + do + { + func->array->value_to_item(i, value_item); + tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC, + value_item, cmp_type); + if (!tree) + break; + i++; + } while (i < func->array->count && tree->type == SEL_TREE::IMPOSSIBLE); + + if (!tree || tree->type == SEL_TREE::IMPOSSIBLE) + { + /* We get here in cases like "t.unsigned NOT IN (-1,-2,-3) */ + tree= NULL; break; + } #define NOT_IN_IGNORE_THRESHOLD 1000 SEL_TREE *tree2; if (func->array->count < NOT_IN_IGNORE_THRESHOLD) { - for (uint i=1; i < func->array->count; i++) + for (; i < func->array->count; i++) { if (func->array->compare_elems(i, i-1)) { @@ -3546,32 +3587,44 @@ static SEL_TREE *get_func_mm_tree(PARAM *param, Item_func *cond_func, func->array->value_to_item(i, value_item); tree2= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC, value_item, cmp_type); - + if (!tree2) + { + tree= NULL; + break; + } + /* Change all intervals to be "c_{i-1} < X < c_i" */ for (uint idx= 0; idx < param->keys; idx++) { - SEL_ARG *new_interval; - if ((new_interval= tree2->keys[idx])) + SEL_ARG *new_interval, *last_val; + if (((new_interval= tree2->keys[idx])) && + ((last_val= tree->keys[idx]->last()))) { - SEL_ARG *last_val= tree->keys[idx]->last(); new_interval->min_value= last_val->max_value; new_interval->min_flag= NEAR_MIN; } } + /* + The following doesn't try to allocate memory so no need to + check for NULL. + */ tree= tree_or(param, tree, tree2); } } } else func->array->value_to_item(func->array->count - 1, value_item); - - /* - Get the SEL_TREE for the last "c_last < X < +inf" interval - (value_item cotains c_last already) - */ - tree2= get_mm_parts(param, cond_func, field, Item_func::GT_FUNC, - value_item, cmp_type); - tree= tree_or(param, tree, tree2); + + if (tree && tree->type != SEL_TREE::IMPOSSIBLE) + { + /* + Get the SEL_TREE for the last "c_last < X < +inf" interval + (value_item cotains c_last already) + */ + tree2= get_mm_parts(param, cond_func, field, Item_func::GT_FUNC, + value_item, cmp_type); + tree= tree_or(param, tree, tree2); + } } else { @@ -5297,6 +5350,7 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree) param->table->file->primary_key_is_clustered()); param->is_ror_scan= !cpk_scan; } + param->n_ranges= 0; records=check_quick_keys(param,idx,tree,param->min_key,0,param->max_key,0); if (records != HA_POS_ERROR) @@ -5304,7 +5358,7 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree) param->table->quick_keys.set_bit(key); param->table->quick_rows[key]=records; param->table->quick_key_parts[key]=param->max_key_part+1; - + param->table->quick_n_ranges[key]= param->n_ranges; if (cpk_scan) param->is_ror_scan= TRUE; } @@ -5440,7 +5494,10 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree, HA_NOSAME && min_key_length == max_key_length && !memcmp(param->min_key,param->max_key,min_key_length)) + { tmp=1; // Max one record + param->n_ranges++; + } else { if (param->is_ror_scan) @@ -5460,6 +5517,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree, is_key_scan_ror(param, keynr, key_tree->part + 1))) param->is_ror_scan= FALSE; } + param->n_ranges++; if (tmp_min_flag & GEOM_FLAG) { diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 2892c5c8b01..4e7b9200d88 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5475,7 +5475,7 @@ ER_SP_DUP_HANDLER 42000 eng "Duplicate handler declared in the same block" ger "Doppelter Handler im selben Block deklariert" ER_SP_NOT_VAR_ARG 42000 - eng "OUT or INOUT argument %d for routine %s is not a variable" + eng "OUT or INOUT argument %d for routine %s is not a variable or NEW pseudo-variable in BEFORE trigger" ger "OUT- oder INOUT-Argument %d für Routine %s ist keine Variable" ER_SP_NO_RETSET 0A000 eng "Not allowed to return a result set from a %s" diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 6a7676c7bf2..174f62c9497 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -310,11 +310,13 @@ sp_prepare_func_item(THD* thd, Item **it_addr) */ bool -sp_eval_expr(THD *thd, Field *result_field, Item *expr_item) +sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr) { + Item *expr_item; + DBUG_ENTER("sp_eval_expr"); - if (!(expr_item= sp_prepare_func_item(thd, &expr_item))) + if (!(expr_item= sp_prepare_func_item(thd, expr_item_ptr))) DBUG_RETURN(TRUE); bool err_status= FALSE; @@ -936,6 +938,7 @@ sp_head::execute(THD *thd) bool err_status= FALSE; uint ip= 0; ulong save_sql_mode; + bool save_abort_on_warning; Query_arena *old_arena; /* per-instruction arena */ MEM_ROOT execute_mem_root; @@ -996,6 +999,10 @@ sp_head::execute(THD *thd) thd->derived_tables= 0; save_sql_mode= thd->variables.sql_mode; thd->variables.sql_mode= m_sql_mode; + save_abort_on_warning= thd->abort_on_warning; + thd->abort_on_warning= + (m_sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)); + /* It is also more efficient to save/restore current thd->lex once when do it in each instruction @@ -1128,6 +1135,7 @@ sp_head::execute(THD *thd) DBUG_ASSERT(!thd->derived_tables); thd->derived_tables= old_derived_tables; thd->variables.sql_mode= save_sql_mode; + thd->abort_on_warning= save_abort_on_warning; thd->stmt_arena= old_arena; state= EXECUTED; @@ -1204,130 +1212,144 @@ bool sp_head::execute_function(THD *thd, Item **argp, uint argcount, Field *return_value_fld) { - Item_cache **param_values; ulonglong binlog_save_options; bool need_binlog_call; - uint params; + uint arg_no; sp_rcontext *octx = thd->spcont; sp_rcontext *nctx = NULL; + char buf[STRING_BUFFER_USUAL_SIZE]; + String binlog_buf(buf, sizeof(buf), &my_charset_bin); bool err_status= FALSE; + MEM_ROOT call_mem_root; + Query_arena call_arena(&call_mem_root, Query_arena::INITIALIZED_FOR_SP); + Query_arena backup_arena; DBUG_ENTER("sp_head::execute_function"); DBUG_PRINT("info", ("function %s", m_name.str)); - params = m_pcont->context_var_count(); - /* Check that the function is called with all specified arguments. If it is not, use my_error() to report an error, or it will not terminate the invoking query properly. */ - - if (argcount != params) + if (argcount != m_pcont->context_var_count()) { /* Need to use my_error here, or it will not terminate the invoking query properly. */ my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0), - "FUNCTION", m_qname.str, params, argcount); + "FUNCTION", m_qname.str, m_pcont->context_var_count(), argcount); DBUG_RETURN(TRUE); } - - /* Allocate param_values to be used for dumping the call into binlog. */ - - if (!(param_values= (Item_cache**)thd->alloc(sizeof(Item_cache*)*argcount))) - DBUG_RETURN(TRUE); - - // QQ Should have some error checking here? (types, etc...) + /* + Prepare arena and memroot for objects which lifetime is whole + duration of function call (sp_rcontext, it's tables and items, + sp_cursor and Item_cache holders for case expressions). + We can't use caller's arena/memroot for those objects because + in this case some fixed amount of memory will be consumed for + each function/trigger invocation and so statements which involve + lot of them will hog memory. + TODO: we should create sp_rcontext once per command and reuse + it on subsequent executions of a function/trigger. + */ + init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0); + thd->set_n_backup_active_arena(&call_arena, &backup_arena); if (!(nctx= new sp_rcontext(m_pcont, return_value_fld, octx)) || nctx->init(thd)) { - delete nctx; /* Delete nctx if it was init() that failed. */ - DBUG_RETURN(TRUE); + thd->restore_active_arena(&call_arena, &backup_arena); + err_status= TRUE; + goto err_with_cleanup; } + /* + We have to switch temporarily back to callers arena/memroot. + Function arguments belong to the caller and so the may reference + memory which they will allocate during calculation long after + this function call will be finished (e.g. in Item::cleanup()). + */ + thd->restore_active_arena(&call_arena, &backup_arena); + #ifndef DBUG_OFF nctx->sp= this; #endif /* Pass arguments. */ + for (arg_no= 0; arg_no < argcount; arg_no++) + { + /* Arguments must be fixed in Item_func_sp::fix_fields */ + DBUG_ASSERT(argp[arg_no]->fixed); + + if ((err_status= nctx->set_variable(thd, arg_no, &(argp[arg_no])))) + goto err_with_cleanup; + } + + need_binlog_call= mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG); + /* + Remember the original arguments for unrolled replication of functions + before they are changed by execution. + */ + if (need_binlog_call) { - uint i; - - for (i= 0 ; i < argcount ; i++) + binlog_buf.length(0); + binlog_buf.append(STRING_WITH_LEN("SELECT ")); + append_identifier(thd, &binlog_buf, m_name.str, m_name.length); + binlog_buf.append('('); + for (arg_no= 0; arg_no < argcount; arg_no++) { - if (!argp[i]->fixed && argp[i]->fix_fields(thd, &argp[i])) - { - err_status= TRUE; - break; - } + String str_value_holder; + String *str_value; - param_values[i]= Item_cache::get_cache(argp[i]->result_type()); - param_values[i]->store(argp[i]); + if (arg_no) + binlog_buf.append(','); - if (nctx->set_variable(thd, i, param_values[i])) - { - err_status= TRUE; - break; - } - } - } + str_value= sp_get_item_value(nctx->get_item(arg_no), + &str_value_holder); - if (err_status) - { - delete nctx; - DBUG_RETURN(TRUE); + if (str_value) + binlog_buf.append(*str_value); + else + binlog_buf.append(STRING_WITH_LEN("NULL")); + } + binlog_buf.append(')'); } - thd->spcont= nctx; binlog_save_options= thd->options; - need_binlog_call= mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG); if (need_binlog_call) { reset_dynamic(&thd->user_var_events); mysql_bin_log.start_union_events(thd); } - + + /* + Switch to call arena/mem_root so objects like sp_cursor or + Item_cache holders for case expressions can be allocated on it. + + TODO: In future we should associate call arena/mem_root with + sp_rcontext and allocate all these objects (and sp_rcontext + itself) on it directly rather than juggle with arenas. + */ + thd->set_n_backup_active_arena(&call_arena, &backup_arena); + thd->options&= ~OPTION_BIN_LOG; err_status= execute(thd); thd->options= binlog_save_options; - + + thd->restore_active_arena(&call_arena, &backup_arena); + if (need_binlog_call) mysql_bin_log.stop_union_events(thd); if (need_binlog_call && thd->binlog_evt_union.unioned_events) { - char buf[256]; - String bufstr(buf, sizeof(buf), &my_charset_bin); - bufstr.length(0); - bufstr.append(STRING_WITH_LEN("SELECT ")); - append_identifier(thd, &bufstr, m_name.str, m_name.length); - bufstr.append('('); - for (uint i=0; i < argcount; i++) - { - String str_value_holder; - String *str_value; - - if (i) - bufstr.append(','); - - str_value= sp_get_item_value(param_values[i], &str_value_holder); - - if (str_value) - bufstr.append(*str_value); - else - bufstr.append(STRING_WITH_LEN("NULL")); - } - bufstr.append(')'); - - Query_log_event qinfo(thd, bufstr.ptr(), bufstr.length(), + Query_log_event qinfo(thd, binlog_buf.ptr(), binlog_buf.length(), thd->binlog_evt_union.unioned_events_trans, FALSE); - if (mysql_bin_log.write(&qinfo) && + if (mysql_bin_log.write(&qinfo) && thd->binlog_evt_union.unioned_events_trans) { push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, @@ -1348,27 +1370,19 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, } } + nctx->pop_all_cursors(); // To avoid memory leaks after an error + +err_with_cleanup: delete nctx; + call_arena.free_items(); + free_root(&call_mem_root, MYF(0)); thd->spcont= octx; DBUG_RETURN(err_status); } -static Item_func_get_user_var *item_is_user_var(Item *it) -{ - if (it->type() == Item::FUNC_ITEM) - { - Item_func *fi= static_cast<Item_func*>(it); - - if (fi->functype() == Item_func::GUSERVAR_FUNC) - return static_cast<Item_func_get_user_var*>(fi); - } - return NULL; -} - - /* Execute a procedure. SYNOPSIS @@ -1444,22 +1458,28 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) for (uint i= 0 ; i < params ; i++) { Item *arg_item= it_args++; - sp_variable_t *spvar= m_pcont->find_variable(i); if (!arg_item) break; + sp_variable_t *spvar= m_pcont->find_variable(i); + if (!spvar) continue; if (spvar->mode != sp_param_in) { - if (!arg_item->is_splocal() && !item_is_user_var(arg_item)) + Settable_routine_parameter *srp= + arg_item->get_settable_routine_parameter(); + + if (!srp) { my_error(ER_SP_NOT_VAR_ARG, MYF(0), i+1, m_qname.str); err_status= TRUE; break; } + + srp->set_required_privilege(spvar->mode == sp_param_inout); } if (spvar->mode == sp_param_out) @@ -1467,7 +1487,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) Item_null *null_item= new Item_null(); if (!null_item || - nctx->set_variable(thd, i, null_item)) + nctx->set_variable(thd, i, (struct Item **)&null_item)) { err_status= TRUE; break; @@ -1475,7 +1495,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) } else { - if (nctx->set_variable(thd, i, *it_args.ref())) + if (nctx->set_variable(thd, i, it_args.ref())) { err_status= TRUE; break; @@ -1527,36 +1547,16 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) if (spvar->mode == sp_param_in) continue; - if (arg_item->is_splocal()) - { - if (octx->set_variable(thd, - ((Item_splocal*) arg_item)->get_var_idx(), - nctx->get_item(i))) - { - err_status= TRUE; - break; - } - } - else + Settable_routine_parameter *srp= + arg_item->get_settable_routine_parameter(); + + DBUG_ASSERT(srp); + + if (srp->set_value(thd, octx, nctx->get_item_addr(i))) { - Item_func_get_user_var *guv= item_is_user_var(arg_item); - - if (guv) - { - Item *item= nctx->get_item(i); - Item_func_set_user_var *suv; - - suv= new Item_func_set_user_var(guv->get_name(), item); - /* - Item_func_set_user_var is not fixed after construction, - call fix_fields(). - */ - if ((err_status= test(!suv || suv->fix_fields(thd, &item) || - suv->check() || suv->update()))) - break; - } + err_status= TRUE; + break; } - } } @@ -2328,7 +2328,7 @@ sp_instr_set::execute(THD *thd, uint *nextp) int sp_instr_set::exec_core(THD *thd, uint *nextp) { - int res= thd->spcont->set_variable(thd, m_offset, m_value); + int res= thd->spcont->set_variable(thd, m_offset, &m_value); if (res && thd->spcont->found_handler_here()) { @@ -2393,12 +2393,7 @@ sp_instr_set_trigger_field::execute(THD *thd, uint *nextp) int sp_instr_set_trigger_field::exec_core(THD *thd, uint *nextp) { - int res= 0; - Item *it= sp_prepare_func_item(thd, &value); - if (!it || - !trigger_field->fixed && trigger_field->fix_fields(thd, 0) || - (it->save_in_field(trigger_field->field, 0) < 0)) - res= -1; + const int res= (trigger_field->set_value(thd, &value) ? -1 : 0); *nextp = m_ip+1; return res; } @@ -2603,7 +2598,7 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp) do it in scope of execution the current context/block. */ - return thd->spcont->set_return_value(thd, m_value); + return thd->spcont->set_return_value(thd, &m_value); } void @@ -3047,7 +3042,7 @@ sp_instr_set_case_expr::execute(THD *thd, uint *nextp) int sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp) { - int res= thd->spcont->set_case_expr(thd, m_case_expr_id, m_case_expr); + int res= thd->spcont->set_case_expr(thd, m_case_expr_id, &m_case_expr); if (res && !thd->spcont->get_case_expr(m_case_expr_id) && @@ -3061,7 +3056,7 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp) Item *null_item= new Item_null(); if (!null_item || - thd->spcont->set_case_expr(thd, m_case_expr_id, null_item)) + thd->spcont->set_case_expr(thd, m_case_expr_id, &null_item)) { /* If this also failed, we have to abort. */ diff --git a/sql/sp_head.h b/sql/sp_head.h index 6a9cf97d739..d5f49d8a964 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -1169,6 +1169,6 @@ Item * sp_prepare_func_item(THD* thd, Item **it_addr); bool -sp_eval_expr(THD *thd, Field *result_field, Item *expr_item); +sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr); #endif /* _SP_HEAD_H_ */ diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 38b6de0e75a..3bc27a029d0 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -150,7 +150,7 @@ sp_rcontext::init_var_items() bool -sp_rcontext::set_return_value(THD *thd, Item *return_value_item) +sp_rcontext::set_return_value(THD *thd, Item **return_value_item) { DBUG_ASSERT(m_return_value_fld); @@ -279,14 +279,14 @@ sp_rcontext::pop_cursors(uint count) int -sp_rcontext::set_variable(THD *thd, uint var_idx, Item *value) +sp_rcontext::set_variable(THD *thd, uint var_idx, Item **value) { return set_variable(thd, m_var_table->field[var_idx], value); } int -sp_rcontext::set_variable(THD *thd, Field *field, Item *value) +sp_rcontext::set_variable(THD *thd, Field *field, Item **value) { if (!value) { @@ -478,9 +478,10 @@ sp_rcontext::create_case_expr_holder(THD *thd, Item_result result_type) */ int -sp_rcontext::set_case_expr(THD *thd, int case_expr_id, Item *case_expr_item) +sp_rcontext::set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr) { - if (!(case_expr_item= sp_prepare_func_item(thd, &case_expr_item))) + Item *case_expr_item= sp_prepare_func_item(thd, case_expr_item_ptr); + if (!case_expr_item) return TRUE; if (!m_case_expr_holders[case_expr_id] || @@ -542,7 +543,7 @@ bool Select_fetch_into_spvars::send_data(List<Item> &items) */ for (; spvar= spvar_iter++, item= item_iter++; ) { - if (thd->spcont->set_variable(thd, spvar->offset, item)) + if (thd->spcont->set_variable(thd, spvar->offset, &item)) return TRUE; } return FALSE; diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index 20aaea3b7c1..30521f6da84 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -91,7 +91,7 @@ class sp_rcontext : public Sql_alloc ~sp_rcontext(); int - set_variable(THD *thd, uint var_idx, Item *value); + set_variable(THD *thd, uint var_idx, Item **value); Item * get_item(uint var_idx); @@ -100,7 +100,7 @@ class sp_rcontext : public Sql_alloc get_item_addr(uint var_idx); bool - set_return_value(THD *thd, Item *return_value_item); + set_return_value(THD *thd, Item **return_value_item); inline bool is_return_value_set() const @@ -200,7 +200,7 @@ class sp_rcontext : public Sql_alloc */ int - set_case_expr(THD *thd, int case_expr_id, Item *case_expr_item); + set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr); Item * get_case_expr(int case_expr_id); @@ -254,7 +254,7 @@ private: Item_cache *create_case_expr_holder(THD *thd, Item_result result_type); - int set_variable(THD *thd, Field *field, Item *value); + int set_variable(THD *thd, Field *field, Item **value); }; // class sp_rcontext : public Sql_alloc diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ec1caba0b5d..02b2f88676f 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -858,8 +858,8 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, if (acl_user->x509_issuer) { DBUG_PRINT("info",("checkpoint 3")); - char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); - DBUG_PRINT("info",("comparing issuers: '%s' and '%s'", + char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); + DBUG_PRINT("info",("comparing issuers: '%s' and '%s'", acl_user->x509_issuer, ptr)); if (strcmp(acl_user->x509_issuer, ptr)) { @@ -6023,20 +6023,21 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, } /* table privileges */ + rw_rdlock(&LOCK_grant); if (grant->version != grant_version) { - rw_rdlock(&LOCK_grant); grant->grant_table= table_hash_search(sctx->host, sctx->ip, db, sctx->priv_user, table, 0); /* purecov: inspected */ grant->version= grant_version; /* purecov: inspected */ - rw_unlock(&LOCK_grant); } if (grant->grant_table != 0) { grant->privilege|= grant->grant_table->privs; } + rw_unlock(&LOCK_grant); + DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); DBUG_VOID_RETURN; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 482a25acbd2..1f3b9e14631 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -617,118 +617,110 @@ static inline uint tmpkeyval(THD *thd, TABLE *table) void close_temporary_tables(THD *thd) { - TABLE *next, - *prev_table /* prev link is not maintained in TABLE's double-linked list */, - *table; - char *query= (gptr) 0, *end; - uint query_buf_size, max_names_len; - bool found_user_tables; - + TABLE *table; if (!thd->temporary_tables) return; - - LINT_INIT(end); - query_buf_size= 50; // Enough for DROP ... TABLE IF EXISTS - /* - insertion sort of temp tables by pseudo_thread_id to build ordered list + if (!mysql_bin_log.is_open()) + { + for (table= thd->temporary_tables; table; table= table->next) + { + close_temporary(table, 1); + } + thd->temporary_tables= 0; + return; + } + + TABLE *next, + *prev_table /* prev link is not maintained in TABLE's double-linked list */; + bool was_quote_show= true; /* to assume thd->options has OPTION_QUOTE_SHOW_CREATE */ + // Better add "if exists", in case a RESET MASTER has been done + const char stub[]= "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS "; + uint stub_len= sizeof(stub) - 1; + char buf[256]; + memcpy(buf, stub, stub_len); + String s_query= String(buf, sizeof(buf), system_charset_info); + bool found_user_tables= false; + LINT_INIT(next); + + /* + insertion sort of temp tables by pseudo_thread_id to build ordered list of sublists of equal pseudo_thread_id */ - for (prev_table= thd->temporary_tables, - table= prev_table->next, - found_user_tables= (prev_table->s->table_name[0] != '#'); + + for (prev_table= thd->temporary_tables, table= prev_table->next; table; prev_table= table, table= table->next) { - TABLE *prev_sorted /* same as for prev_table */, - *sorted; - /* - table not created directly by the user is moved to the tail. - Fixme/todo: nothing (I checked the manual) prevents user to create temp - with `#' - */ - if (table->s->table_name[0] == '#') - continue; - else - { - found_user_tables = 1; - } - for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table; - prev_sorted= sorted, sorted= sorted->next) + TABLE *prev_sorted /* same as for prev_table */, *sorted; + if (is_user_table(table)) { - if (sorted->s->table_name[0] == '#' || tmpkeyval(thd, sorted) > tmpkeyval(thd, table)) + if (!found_user_tables) + found_user_tables= true; + for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table; + prev_sorted= sorted, sorted= sorted->next) { - /* move into the sorted part of the list from the unsorted */ - prev_table->next= table->next; - table->next= sorted; - if (prev_sorted) + if (!is_user_table(sorted) || + tmpkeyval(thd, sorted) > tmpkeyval(thd, table)) { - prev_sorted->next= table; - } - else - { - thd->temporary_tables= table; + /* move into the sorted part of the list from the unsorted */ + prev_table->next= table->next; + table->next= sorted; + if (prev_sorted) + { + prev_sorted->next= table; + } + else + { + thd->temporary_tables= table; + } + table= prev_table; + break; } - table= prev_table; - break; } } - } - /* - calc query_buf_size as max per sublists, one sublist per pseudo thread id. - Also stop at first occurence of `#'-named table that starts - all implicitly created temp tables - */ - for (max_names_len= 0, table=thd->temporary_tables; - table && table->s->table_name[0] != '#'; - table=table->next) + } + + /* We always quote db,table names though it is slight overkill */ + if (found_user_tables && + !(was_quote_show= (thd->options & OPTION_QUOTE_SHOW_CREATE))) { - uint tmp_names_len; - for (tmp_names_len= table->s->key_length + 1; - table->next && table->s->table_name[0] != '#' && - tmpkeyval(thd, table) == tmpkeyval(thd, table->next); - table=table->next) - { - /* - We are going to add 4 ` around the db/table names, so 1 might not look - enough; indeed it is enough, because table->key_length is greater (by 8, - because of server_id and thread_id) than db||table. - */ - tmp_names_len += table->next->s->key_length + 1; - } - if (tmp_names_len > max_names_len) max_names_len= tmp_names_len; + thd->options |= OPTION_QUOTE_SHOW_CREATE; } - - /* allocate */ - if (found_user_tables && mysql_bin_log.is_open() && - (query = alloc_root(thd->mem_root, query_buf_size+= max_names_len))) - // Better add "if exists", in case a RESET MASTER has been done - end= strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS "); /* scan sorted tmps to generate sequence of DROP */ - for (table=thd->temporary_tables; table; table= next) + for (table= thd->temporary_tables; table; table= next) { - if (query // we might be out of memory, but this is not fatal - && table->s->table_name[0] != '#') + if (is_user_table(table)) { - char *end_cur; /* Set pseudo_thread_id to be that of the processed table */ thd->variables.pseudo_thread_id= tmpkeyval(thd, table); /* Loop forward through all tables within the sublist of common pseudo_thread_id to create single DROP query */ - for (end_cur= end; - table && table->s->table_name[0] != '#' && + for (s_query.length(stub_len); + table && is_user_table(table) && tmpkeyval(thd, table) == thd->variables.pseudo_thread_id; table= next) { - end_cur= strxmov(end_cur, "`", table->s->db, "`.`", - table->s->table_name, "`,", NullS); + /* + We are going to add 4 ` around the db/table names and possible more + due to special characters in the names + */ + append_identifier(thd, &s_query, table->s->db, strlen(table->s->db)); + s_query.q_append('.'); + append_identifier(thd, &s_query, table->s->table_name, + strlen(table->s->table_name)); + s_query.q_append(','); next= table->next; close_temporary(table, 1); } thd->clear_error(); - /* The -1 is to remove last ',' */ - Query_log_event qinfo(thd, query, (ulong)(end_cur - query) - 1, 0, FALSE); + CHARSET_INFO *cs_save= thd->variables.character_set_client; + thd->variables.character_set_client= system_charset_info; + Query_log_event qinfo(thd, s_query.ptr(), + s_query.length() - 1 /* to remove trailing ',' */, + 0, FALSE); + thd->variables.character_set_client= cs_save; /* Imagine the thread had created a temp table, then was doing a SELECT, and the SELECT was killed. Then it's not clever to mark the statement above as @@ -741,12 +733,14 @@ void close_temporary_tables(THD *thd) qinfo.error_code= 0; mysql_bin_log.write(&qinfo); } - else + else { next= table->next; close_temporary(table, 1); } } + if (!was_quote_show) + thd->options &= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */ thd->temporary_tables=0; } @@ -1160,6 +1154,8 @@ bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list) MYSQL_LOCK_IGNORE_FLUSH - Open table even if someone has done a flush or namelock on it. No version number checking is done. + MYSQL_OPEN_IGNORE_LOCKED_TABLES - Open table + ignoring set of locked tables and prelocked mode. IMPLEMENTATION Uses a cache of open tables to find a table not in use. @@ -1219,7 +1215,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, } } - if (thd->locked_tables || thd->prelocked_mode) + if (!(flags & MYSQL_OPEN_IGNORE_LOCKED_TABLES) && + (thd->locked_tables || thd->prelocked_mode)) { // Using table locks TABLE *best_table= 0; int best_distance= INT_MIN; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 026c3e0d515..65fd4d3ac19 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1877,7 +1877,7 @@ bool select_dumpvar::send_data(List<Item> &items) if ((yy=var_li++)) { if (thd->spcont->set_variable(current_thd, yy->get_var_idx(), - *it.ref())) + it.ref())) DBUG_RETURN(1); } } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 320b8e1df9d..c054499ecd8 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2437,6 +2437,153 @@ bool select_insert::send_eof() CREATE TABLE (SELECT) ... ***************************************************************************/ +/* + Create table from lists of fields and items (or open existing table + with same name). + + SYNOPSIS + create_table_from_items() + thd in Thread object + create_info in Create information (like MAX_ROWS, ENGINE or + temporary table flag) + create_table in Pointer to TABLE_LIST object providing database + and name for table to be created or to be open + extra_fields in/out Initial list of fields for table to be created + keys in List of keys for table to be created + items in List of items which should be used to produce rest + of fields for the table (corresponding fields will + be added to the end of 'extra_fields' list) + lock out Pointer to the MYSQL_LOCK object for table created + (open) will be returned in this parameter. Since + this table is not included in THD::lock caller is + responsible for explicitly unlocking this table. + + NOTES + If 'create_info->options' bitmask has HA_LEX_CREATE_IF_NOT_EXISTS + flag and table with name provided already exists then this function will + simply open existing table. + Also note that create, open and lock sequence in this function is not + atomic and thus contains gap for deadlock and can cause other troubles. + Since this function contains some logic specific to CREATE TABLE ... SELECT + it should be changed before it can be used in other contexts. + + RETURN VALUES + non-zero Pointer to TABLE object for table created or opened + 0 Error +*/ + +static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, + TABLE_LIST *create_table, + List<create_field> *extra_fields, + List<Key> *keys, List<Item> *items, + MYSQL_LOCK **lock) +{ + TABLE tmp_table; // Used during 'create_field()' + TABLE *table= 0; + uint select_field_count= items->elements; + /* Add selected items to field list */ + List_iterator_fast<Item> it(*items); + Item *item; + Field *tmp_field; + bool not_used; + DBUG_ENTER("create_table_from_items"); + + tmp_table.alias= 0; + tmp_table.timestamp_field= 0; + tmp_table.s= &tmp_table.share_not_to_be_used; + tmp_table.s->db_create_options=0; + tmp_table.s->blob_ptr_size= portable_sizeof_char_ptr; + tmp_table.s->db_low_byte_first= test(create_info->db_type == DB_TYPE_MYISAM || + create_info->db_type == DB_TYPE_HEAP); + tmp_table.null_row=tmp_table.maybe_null=0; + + while ((item=it++)) + { + create_field *cr_field; + Field *field; + if (item->type() == Item::FUNC_ITEM) + field=item->tmp_table_field(&tmp_table); + else + field=create_tmp_field(thd, &tmp_table, item, item->type(), + (Item ***) 0, &tmp_field, 0, 0, 0, 0, 0); + if (!field || + !(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ? + ((Item_field *)item)->field : + (Field*) 0)))) + DBUG_RETURN(0); + if (item->maybe_null) + cr_field->flags &= ~NOT_NULL_FLAG; + extra_fields->push_back(cr_field); + } + /* + create and lock table + + We don't log the statement, it will be logged later. + + If this is a HEAP table, the automatic DELETE FROM which is written to the + binlog when a HEAP table is opened for the first time since startup, must + not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we + don't want to delete from it) 2) it would be written before the CREATE + TABLE, which is a wrong order. So we keep binary logging disabled when we + open_table(). + NOTE: By locking table which we just have created (or for which we just have + have found that it already exists) separately from other tables used by the + statement we create potential window for deadlock. + TODO: create and open should be done atomic ! + */ + { + tmp_disable_binlog(thd); + if (!mysql_create_table(thd, create_table->db, create_table->table_name, + create_info, *extra_fields, *keys, 0, + select_field_count)) + { + /* + If we are here in prelocked mode we either create temporary table + or prelocked mode is caused by the SELECT part of this statement. + */ + DBUG_ASSERT(!thd->prelocked_mode || + create_info->options & HA_LEX_CREATE_TMP_TABLE || + thd->lex->requires_prelocking()); + + /* + NOTE: We don't want to ignore set of locked tables here if we are + under explicit LOCK TABLES since it will open gap for deadlock + too wide (and also is not backward compatible). + */ + if (! (table= open_table(thd, create_table, thd->mem_root, (bool*) 0, + (MYSQL_LOCK_IGNORE_FLUSH | + ((thd->prelocked_mode == PRELOCKED) ? + MYSQL_OPEN_IGNORE_LOCKED_TABLES:0))))) + quick_rm_table(create_info->db_type, create_table->db, + table_case_name(create_info, create_table->table_name)); + } + reenable_binlog(thd); + if (!table) // open failed + DBUG_RETURN(0); + } + + /* + FIXME: What happens if trigger manages to be created while we are + obtaining this lock ? May be it is sensible just to disable + trigger execution in this case ? Or will MYSQL_LOCK_IGNORE_FLUSH + save us from that ? + */ + table->reginfo.lock_type=TL_WRITE; + if (! ((*lock)= mysql_lock_tables(thd, &table, 1, + MYSQL_LOCK_IGNORE_FLUSH, ¬_used))) + { + VOID(pthread_mutex_lock(&LOCK_open)); + hash_delete(&open_cache,(byte*) table); + VOID(pthread_mutex_unlock(&LOCK_open)); + quick_rm_table(create_info->db_type, create_table->db, + table_case_name(create_info, create_table->table_name)); + DBUG_RETURN(0); + } + table->file->extra(HA_EXTRA_WRITE_CACHE); + DBUG_RETURN(table); +} + + int select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a8de7ff0154..7d62e5bb405 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5709,6 +5709,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length) } else { + DBUG_ASSERT(thd->net.report_error); DBUG_PRINT("info",("Command aborted. Fatal_error: %d", thd->is_fatal_error)); query_cache_abort(&thd->net); @@ -7226,7 +7227,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, lex->create_info.merge_list.first)) goto err; if (grant_option && want_priv != CREATE_TMP_ACL && - check_grant(thd, want_priv, create_table, 0, UINT_MAX, 0)) + check_grant(thd, want_priv, create_table, 0, 1, 0)) goto err; if (select_lex->item_list.elements) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 465f41fa8de..d36ceedc7ae 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3335,7 +3335,10 @@ best_access_path(JOIN *join, uint key= keyuse->key; KEY *keyinfo= table->key_info+key; bool ft_key= (keyuse->keypart == FT_KEYPART); - uint found_ref_or_null= 0; + /* Bitmap of keyparts where the ref access is over 'keypart=const': */ + key_part_map const_part= 0; + /* The or-null keypart in ref-or-null access: */ + key_part_map ref_or_null_part= 0; /* Calculate how many key segments of the current key we can use */ start_key= keyuse; @@ -3347,12 +3350,14 @@ best_access_path(JOIN *join, do { if (!(remaining_tables & keyuse->used_tables) && - !(found_ref_or_null & keyuse->optimize)) + !(ref_or_null_part && (keyuse->optimize & + KEY_OPTIMIZE_REF_OR_NULL))) { found_part|= keyuse->keypart_map; - double tmp= prev_record_reads(join, - (found_ref | - keyuse->used_tables)); + if (!(keyuse->used_tables & ~join->const_table_map)) + const_part|= keyuse->keypart_map; + double tmp= prev_record_reads(join, (found_ref | + keyuse->used_tables)); if (tmp < best_prev_record_reads) { best_part_found_ref= keyuse->used_tables; @@ -3364,8 +3369,8 @@ best_access_path(JOIN *join, If there is one 'key_column IS NULL' expression, we can use this ref_or_null optimisation of this field */ - found_ref_or_null|= (keyuse->optimize & - KEY_OPTIMIZE_REF_OR_NULL); + if (keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL) + ref_or_null_part |= keyuse->keypart_map; } keyuse++; } while (keyuse->table == table && keyuse->key == key && @@ -3401,7 +3406,7 @@ best_access_path(JOIN *join, Check if we found full key */ if (found_part == PREV_BITS(uint,keyinfo->key_parts) && - !found_ref_or_null) + !ref_or_null_part) { /* use eq key */ max_key_part= (uint) ~0; if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) @@ -3413,6 +3418,23 @@ best_access_path(JOIN *join, { if (!found_ref) { /* We found a const key */ + /* + ReuseRangeEstimateForRef-1: + We get here if we've found a ref(const) (c_i are constants): + "(keypart1=c1) AND ... AND (keypartN=cN)" [ref_const_cond] + + If range optimizer was able to construct a "range" + access on this index, then its condition "quick_cond" was + eqivalent to ref_const_cond (*), and we can re-use E(#rows) + from the range optimizer. + + Proof of (*): By properties of range and ref optimizers + quick_cond will be equal or tighther than ref_const_cond. + ref_const_cond already covers "smallest" possible interval - + a singlepoint interval over all keyparts. Therefore, + quick_cond is equivalent to ref_const_cond (if it was an + empty interval we wouldn't have got here). + */ if (table->quick_keys.is_set(key)) records= (double) table->quick_rows[key]; else @@ -3433,6 +3455,23 @@ best_access_path(JOIN *join, if (records < 2.0) records=2.0; /* Can't be as good as a unique */ } + /* + ReuseRangeEstimateForRef-2: We get here if we could not reuse + E(#rows) from range optimizer. Make another try: + + If range optimizer produced E(#rows) for a prefix of the ref + access we're considering, and that E(#rows) is lower then our + current estimate, make an adjustment. The criteria of when we + can make an adjustment is a special case of the criteria used + in ReuseRangeEstimateForRef-3. + */ + if (table->quick_keys.is_set(key) && + const_part & (1 << table->quick_key_parts[key]) && + table->quick_n_ranges[key] == 1 && + records > (double) table->quick_rows[key]) + { + records= (double) table->quick_rows[key]; + } } /* Limit the number of matched rows */ tmp= records; @@ -3461,12 +3500,50 @@ best_access_path(JOIN *join, { max_key_part= max_part_bit(found_part); /* - Check if quick_range could determinate how many rows we - will match + ReuseRangeEstimateForRef-3: + We're now considering a ref[or_null] access via + (t.keypart1=e1 AND ... AND t.keypartK=eK) [ OR + (same-as-above but with one cond replaced + with "t.keypart_i IS NULL")] (**) + + Try re-using E(#rows) from "range" optimizer: + We can do so if "range" optimizer used the same intervals as + in (**). The intervals used by range optimizer may be not + available at this point (as "range" access might have choosen to + create quick select over another index), so we can't compare + them to (**). We'll make indirect judgements instead. + The sufficient conditions for re-use are: + (C1) All e_i in (**) are constants, i.e. found_ref==FALSE. (if + this is not satisfied we have no way to know which ranges + will be actually scanned by 'ref' until we execute the + join) + (C2) max #key parts in 'range' access == K == max_key_part (this + is apparently a necessary requirement) + + We also have a property that "range optimizer produces equal or + tighter set of scan intervals than ref(const) optimizer". Each + of the intervals in (**) are "tightest possible" intervals when + one limits itself to using keyparts 1..K (which we do in #2). + From here it follows that range access used either one, or + both of the (I1) and (I2) intervals: + + (t.keypart1=c1 AND ... AND t.keypartK=eK) (I1) + (same-as-above but with one cond replaced + with "t.keypart_i IS NULL") (I2) + + The remaining part is to exclude the situation where range + optimizer used one interval while we're considering + ref-or-null and looking for estimate for two intervals. This + is done by last limitation: + + (C3) "range optimizer used (have ref_or_null?2:1) intervals" */ - if (table->quick_keys.is_set(key) && - table->quick_key_parts[key] == max_key_part) + if (table->quick_keys.is_set(key) && !found_ref && //(C1) + table->quick_key_parts[key] == max_key_part && //(C2) + table->quick_n_ranges[key] == 1+test(ref_or_null_part)) //(C3) + { tmp= records= (double) table->quick_rows[key]; + } else { /* Check if we have statistic about the distribution */ @@ -3510,21 +3587,37 @@ best_access_path(JOIN *join, } records = (ulong) tmp; } + + if (ref_or_null_part) + { + /* We need to do two key searches to find key */ + tmp *= 2.0; + records *= 2.0; + } + /* - If quick_select was used on a part of this key, we know - the maximum number of rows that the key can match. + ReuseRangeEstimateForRef-4: We get here if we could not reuse + E(#rows) from range optimizer. Make another try: + + If range optimizer produced E(#rows) for a prefix of the ref + access we're considering, and that E(#rows) is lower then our + current estimate, make the adjustment. + + The decision whether we can re-use the estimate from the range + optimizer is the same as in ReuseRangeEstimateForRef-3, + applied to first table->quick_key_parts[key] key parts. */ if (table->quick_keys.is_set(key) && table->quick_key_parts[key] <= max_key_part && + const_part & (1 << table->quick_key_parts[key]) && + table->quick_n_ranges[key] == 1 + test(ref_or_null_part & + const_part) && records > (double) table->quick_rows[key]) - tmp= records= (double) table->quick_rows[key]; - else if (found_ref_or_null) { - /* We need to do two key searches to find key */ - tmp *= 2.0; - records *= 2.0; + tmp= records= (double) table->quick_rows[key]; } } + /* Limit the number of matched rows */ set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key); if (table->used_keys.is_set(key)) @@ -4340,344 +4433,11 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent) && (!idx|| !check_interleaving_with_nj(join->positions[idx-1].table, s))) { - double best,best_time,records; - best=best_time=records=DBL_MAX; - KEYUSE *best_key=0; - uint best_max_key_part=0; - my_bool found_constraint= 0; - - if (s->keyuse) - { /* Use key if possible */ - TABLE *table=s->table; - KEYUSE *keyuse,*start_key=0; - double best_records=DBL_MAX; - uint max_key_part=0; - - /* Test how we can use keys */ - rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE; // Assumed records/key - for (keyuse=s->keyuse ; keyuse->table == table ;) - { - key_part_map found_part=0; - table_map found_ref=0; - uint key=keyuse->key; - KEY *keyinfo=table->key_info+key; - bool ft_key=(keyuse->keypart == FT_KEYPART); - uint found_ref_or_null= 0; - - /* Calculate how many key segments of the current key we can use */ - start_key=keyuse; - do - { - uint keypart=keyuse->keypart; - table_map best_part_found_ref= 0; - double best_prev_record_reads= DBL_MAX; - do - { - if (!(rest_tables & keyuse->used_tables) && - !(found_ref_or_null & keyuse->optimize)) - { - found_part|=keyuse->keypart_map; - double tmp= prev_record_reads(join, - (found_ref | - keyuse->used_tables)); - if (tmp < best_prev_record_reads) - { - best_part_found_ref= keyuse->used_tables; - best_prev_record_reads= tmp; - } - if (rec > keyuse->ref_table_rows) - rec= keyuse->ref_table_rows; - /* - If there is one 'key_column IS NULL' expression, we can - use this ref_or_null optimisation of this field - */ - found_ref_or_null|= (keyuse->optimize & - KEY_OPTIMIZE_REF_OR_NULL); - } - keyuse++; - } while (keyuse->table == table && keyuse->key == key && - keyuse->keypart == keypart); - found_ref|= best_part_found_ref; - } while (keyuse->table == table && keyuse->key == key); - - /* - Assume that that each key matches a proportional part of table. - */ - if (!found_part && !ft_key) - continue; // Nothing usable found - if (rec < MATCHING_ROWS_IN_OTHER_TABLE) - rec= MATCHING_ROWS_IN_OTHER_TABLE; // Fix for small tables - - /* - ft-keys require special treatment - */ - if (ft_key) - { - /* - Really, there should be records=0.0 (yes!) - but 1.0 would be probably safer - */ - tmp=prev_record_reads(join,found_ref); - records=1.0; - } - else - { - found_constraint= 1; - /* - Check if we found full key - */ - if (found_part == PREV_BITS(uint,keyinfo->key_parts) && - !found_ref_or_null) - { /* use eq key */ - max_key_part= (uint) ~0; - if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY | - HA_END_SPACE_KEY)) == HA_NOSAME) - { - tmp=prev_record_reads(join,found_ref); - records=1.0; - } - else - { - if (!found_ref) - { // We found a const key - if (table->quick_keys.is_set(key)) - records= (double) table->quick_rows[key]; - else - { - /* quick_range couldn't use key! */ - records= (double) s->records/rec; - } - } - else - { - if (!(records=keyinfo->rec_per_key[keyinfo->key_parts-1])) - { // Prefere longer keys - records= - ((double) s->records / (double) rec * - (1.0 + - ((double) (table->s->max_key_length-keyinfo->key_length) / - (double) table->s->max_key_length))); - if (records < 2.0) - records=2.0; // Can't be as good as a unique - } - } - /* Limit the number of matched rows */ - tmp= records; - set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key); - if (table->used_keys.is_set(key)) - { - /* we can use only index tree */ - uint keys_per_block= table->file->block_size/2/ - (keyinfo->key_length+table->file->ref_length)+1; - tmp=record_count*(tmp+keys_per_block-1)/keys_per_block; - } - else - tmp=record_count*min(tmp,s->worst_seeks); - } - } - else - { - /* - Use as much key-parts as possible and a uniq key is better - than a not unique key - Set tmp to (previous record count) * (records / combination) - */ - if ((found_part & 1) && - (!(table->file->index_flags(key,0,0) & HA_ONLY_WHOLE_INDEX) || - found_part == PREV_BITS(uint,keyinfo->key_parts))) - { - max_key_part=max_part_bit(found_part); - /* - Check if quick_range could determinate how many rows we - will match - */ - if (table->quick_keys.is_set(key) && - table->quick_key_parts[key] == max_key_part) - tmp=records= (double) table->quick_rows[key]; - else - { - /* Check if we have statistic about the distribution */ - if ((records=keyinfo->rec_per_key[max_key_part-1])) - tmp=records; - else - { - /* - Assume that the first key part matches 1% of the file - and that the whole key matches 10 (duplicates) or 1 - (unique) records. - Assume also that more key matches proportionally more - records - This gives the formula: - records= (x * (b-a) + a*c-b)/(c-1) - - b = records matched by whole key - a = records matched by first key part (10% of all records?) - c = number of key parts in key - x = used key parts (1 <= x <= c) - */ - double rec_per_key; - rec_per_key= keyinfo->rec_per_key[keyinfo->key_parts-1] ? - (double) keyinfo->rec_per_key[keyinfo->key_parts-1] : - (double) s->records/rec+1; - if (!s->records) - tmp=0; - else if (rec_per_key/(double) s->records >= 0.01) - tmp=rec_per_key; - else - { - double a=s->records*0.01; - tmp=(max_key_part * (rec_per_key - a) + - a*keyinfo->key_parts - rec_per_key)/ - (keyinfo->key_parts-1); - set_if_bigger(tmp,1.0); - } - records=(ulong) tmp; - } - /* - If quick_select was used on a part of this key, we know - the maximum number of rows that the key can match. - */ - if (table->quick_keys.is_set(key) && - table->quick_key_parts[key] <= max_key_part && - records > (double) table->quick_rows[key]) - tmp= records= (double) table->quick_rows[key]; - else if (found_ref_or_null) - { - /* We need to do two key searches to find key */ - tmp*= 2.0; - records*= 2.0; - } - } - /* Limit the number of matched rows */ - set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key); - if (table->used_keys.is_set(key)) - { - /* we can use only index tree */ - uint keys_per_block= table->file->block_size/2/ - (keyinfo->key_length+table->file->ref_length)+1; - tmp=record_count*(tmp+keys_per_block-1)/keys_per_block; - } - else - tmp=record_count*min(tmp,s->worst_seeks); - } - else - tmp=best_time; // Do nothing - } - } /* not ft_key */ - if (tmp < best_time - records/(double) TIME_FOR_COMPARE) - { - best_time=tmp + records/(double) TIME_FOR_COMPARE; - best=tmp; - best_records=records; - best_key=start_key; - best_max_key_part=max_key_part; - } - } - records=best_records; - } - - /* - Don't test table scan if it can't be better. - Prefer key lookup if we would use the same key for scanning. - - Don't do a table scan on InnoDB tables, if we can read the used - parts of the row from any of the used index. - This is because table scans uses index and we would not win - anything by using a table scan. - (see comment in best_access_path() for more details on the below - condition) - */ - if ((records >= s->found_records || best > s->read_time) && - !(s->quick && best_key && s->quick->index == best_key->key && - best_max_key_part >= s->table->quick_key_parts[best_key->key]) && - !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) && - ! s->table->used_keys.is_clear_all() && best_key) && - !(s->table->force_index && best_key && !s->quick)) - { // Check full join - ha_rows rnd_records= s->found_records; - /* - If there is a restriction on the table, assume that 25% of the - rows can be skipped on next part. - This is to force tables that this table depends on before this - table - */ - if (found_constraint) - rnd_records-= rnd_records/4; - - /* - Range optimizer never proposes a RANGE if it isn't better - than FULL: so if RANGE is present, it's always preferred to FULL. - Here we estimate its cost. - */ - if (s->quick) - { - /* - For each record we: - - read record range through 'quick' - - skip rows which does not satisfy WHERE constraints - */ - tmp= record_count * - (s->quick->read_time + - (s->found_records - rnd_records)/(double) TIME_FOR_COMPARE); - } - else - { - /* Estimate cost of reading table. */ - tmp= s->table->file->scan_time(); - if (s->table->map & join->outer_join) // Can't use join cache - { - /* - For each record we have to: - - read the whole table record - - skip rows which does not satisfy join condition - */ - tmp= record_count * - (tmp + - (s->records - rnd_records)/(double) TIME_FOR_COMPARE); - } - else - { - /* We read the table as many times as join buffer becomes full. */ - tmp*= (1.0 + floor((double) cache_record_length(join,idx) * - record_count / - (double) thd->variables.join_buff_size)); - /* - We don't make full cartesian product between rows in the scanned - table and existing records because we skip all rows from the - scanned table, which does not satisfy join condition when - we read the table (see flush_cached_records for details). Here we - take into account cost to read and skip these records. - */ - tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE; - } - } - - /* - We estimate the cost of evaluating WHERE clause for found records - as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus - tmp give us total cost of using TABLE SCAN - */ - if (best == DBL_MAX || - (tmp + record_count/(double) TIME_FOR_COMPARE*rnd_records < - best + record_count/(double) TIME_FOR_COMPARE*records)) - { - /* - If the table has a range (s->quick is set) make_join_select() - will ensure that this will be used - */ - best=tmp; - records= rows2double(rnd_records); - best_key=0; - } - } - join->positions[idx].records_read= records; - join->positions[idx].key=best_key; - join->positions[idx].table= s; - if (!best_key && idx == join->const_tables && - s->table == join->sort_by_table && - join->unit->select_limit_cnt >= records) - join->sort_by_table= (TABLE*) 1; // Must use temporary table - + double records, best; + best_access_path(join, s, thd, rest_tables, idx, record_count, + read_time); + records= join->positions[idx].records_read; + best= join->positions[idx].read_time; /* Go to the next level only if there hasn't been a better key on this level! This will cut down the search for a lot simple cases! @@ -12739,6 +12499,17 @@ create_distinct_group(THD *thd, Item **ref_pointer_array, { if (!item->const_item() && !item->with_sum_func && !item->marker) { + /* + Don't put duplicate columns from the SELECT list into the + GROUP BY list. + */ + ORDER *ord_iter; + for (ord_iter= group; ord_iter; ord_iter= ord_iter->next) + if ((*ord_iter->item)->eq(item, 1)) + break; + if (ord_iter) + continue; + ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER)); if (!ord) return 0; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 126abb96f61..70bdef302df 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2662,7 +2662,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, field->real_type() == MYSQL_TYPE_STRING) // For binary type { uint32 octet_max_length= field->max_length(); - if (octet_max_length != (uint32) 4294967295U) + if (is_blob && octet_max_length != (uint32) 4294967295U) octet_max_length /= field->charset()->mbmaxlen; longlong char_max_len= is_blob ? (longlong) octet_max_length / field->charset()->mbminlen : @@ -2854,17 +2854,18 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, const char *wild, bool full_access, const char *sp_user) { String tmp_string; + String sp_db, sp_name, definer; TIME time; LEX *lex= thd->lex; CHARSET_INFO *cs= system_charset_info; - const char *sp_db, *sp_name, *definer; - sp_db= get_field(thd->mem_root, proc_table->field[0]); - sp_name= get_field(thd->mem_root, proc_table->field[1]); - definer= get_field(thd->mem_root, proc_table->field[11]); + get_field(thd->mem_root, proc_table->field[0], &sp_db); + get_field(thd->mem_root, proc_table->field[1], &sp_name); + get_field(thd->mem_root, proc_table->field[11], &definer); if (!full_access) - full_access= !strcmp(sp_user, definer); - if (!full_access && check_some_routine_access(thd, sp_db, sp_name, - proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE)) + full_access= !strcmp(sp_user, definer.ptr()); + if (!full_access && check_some_routine_access(thd, sp_db.ptr(), sp_name.ptr(), + proc_table->field[2]->val_int() == + TYPE_ENUM_PROCEDURE)) return 0; if (lex->orig_sql_command == SQLCOM_SHOW_STATUS_PROC && @@ -2874,13 +2875,13 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, lex->orig_sql_command == SQLCOM_END) { restore_record(table, s->default_values); - if (!wild || !wild[0] || !wild_compare(sp_name, wild, 0)) + if (!wild || !wild[0] || !wild_compare(sp_name.ptr(), wild, 0)) { int enum_idx= proc_table->field[5]->val_int(); - table->field[3]->store(sp_name, strlen(sp_name), cs); + table->field[3]->store(sp_name.ptr(), sp_name.length(), cs); get_field(thd->mem_root, proc_table->field[3], &tmp_string); table->field[0]->store(tmp_string.ptr(), tmp_string.length(), cs); - table->field[2]->store(sp_db, strlen(sp_db), cs); + table->field[2]->store(sp_db.ptr(), sp_db.length(), cs); get_field(thd->mem_root, proc_table->field[2], &tmp_string); table->field[4]->store(tmp_string.ptr(), tmp_string.length(), cs); if (proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION) @@ -2912,7 +2913,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, table->field[17]->store(tmp_string.ptr(), tmp_string.length(), cs); get_field(thd->mem_root, proc_table->field[15], &tmp_string); table->field[18]->store(tmp_string.ptr(), tmp_string.length(), cs); - table->field[19]->store(definer, strlen(definer), cs); + table->field[19]->store(definer.ptr(), definer.length(), cs); return schema_table_store_record(thd, table); } } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c9e9ce1bba7..32a86b0f39a 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1796,105 +1796,6 @@ make_unique_key_name(const char *field_name,KEY *start,KEY *end) /**************************************************************************** -** Create table from a list of fields and items -****************************************************************************/ - -TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, - TABLE_LIST *create_table, - List<create_field> *extra_fields, - List<Key> *keys, - List<Item> *items, - MYSQL_LOCK **lock) -{ - TABLE tmp_table; // Used during 'create_field()' - TABLE *table= 0; - uint select_field_count= items->elements; - /* Add selected items to field list */ - List_iterator_fast<Item> it(*items); - Item *item; - Field *tmp_field; - bool not_used; - DBUG_ENTER("create_table_from_items"); - - tmp_table.alias= 0; - tmp_table.timestamp_field= 0; - tmp_table.s= &tmp_table.share_not_to_be_used; - tmp_table.s->db_create_options=0; - tmp_table.s->blob_ptr_size= portable_sizeof_char_ptr; - tmp_table.s->db_low_byte_first= test(create_info->db_type == DB_TYPE_MYISAM || - create_info->db_type == DB_TYPE_HEAP); - tmp_table.null_row=tmp_table.maybe_null=0; - - while ((item=it++)) - { - create_field *cr_field; - Field *field; - if (item->type() == Item::FUNC_ITEM) - field=item->tmp_table_field(&tmp_table); - else - field=create_tmp_field(thd, &tmp_table, item, item->type(), - (Item ***) 0, &tmp_field, 0, 0, 0, 0, 0); - if (!field || - !(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ? - ((Item_field *)item)->field : - (Field*) 0)))) - DBUG_RETURN(0); - if (item->maybe_null) - cr_field->flags &= ~NOT_NULL_FLAG; - extra_fields->push_back(cr_field); - } - /* - create and lock table - - We don't log the statement, it will be logged later. - - If this is a HEAP table, the automatic DELETE FROM which is written to the - binlog when a HEAP table is opened for the first time since startup, must - not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we - don't want to delete from it) 2) it would be written before the CREATE - TABLE, which is a wrong order. So we keep binary logging disabled when we - open_table(). - TODO: create and open should be done atomic ! - */ - { - tmp_disable_binlog(thd); - if (!mysql_create_table(thd, create_table->db, create_table->table_name, - create_info, *extra_fields, *keys, 0, - select_field_count)) - { - if (! (table= open_table(thd, create_table, thd->mem_root, (bool*) 0, - MYSQL_LOCK_IGNORE_FLUSH))) - quick_rm_table(create_info->db_type, create_table->db, - table_case_name(create_info, create_table->table_name)); - } - reenable_binlog(thd); - if (!table) // open failed - DBUG_RETURN(0); - } - - /* - FIXME: What happens if trigger manages to be created while we are - obtaining this lock ? May be it is sensible just to disable - trigger execution in this case ? Or will MYSQL_LOCK_IGNORE_FLUSH - save us from that ? - */ - table->reginfo.lock_type=TL_WRITE; - if (! ((*lock)= mysql_lock_tables(thd, &table, 1, - MYSQL_LOCK_IGNORE_FLUSH, ¬_used))) - { - VOID(pthread_mutex_lock(&LOCK_open)); - hash_delete(&open_cache,(byte*) table); - VOID(pthread_mutex_unlock(&LOCK_open)); - quick_rm_table(create_info->db_type, create_table->db, - table_case_name(create_info, create_table->table_name)); - DBUG_RETURN(0); - } - table->file->extra(HA_EXTRA_WRITE_CACHE); - DBUG_RETURN(table); -} - - -/**************************************************************************** ** Alter a table definition ****************************************************************************/ @@ -3324,7 +3225,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, DBUG_PRINT("info", ("old type: %d new type: %d", old_db_type, new_db_type)); if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) || - ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED)) + ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED) || + (old_db_type != new_db_type && + ha_check_storage_engine_flag(new_db_type, HTON_ALTER_CANNOT_CREATE))) { DBUG_PRINT("info", ("doesn't support alter")); my_error(ER_ILLEGAL_HA, MYF(0), table_name); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6473163a6ec..b2dbc517fa4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -448,6 +448,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token NUMERIC_SYM %token NVARCHAR_SYM %token OFFSET_SYM +%token OJ_SYM %token OLD_PASSWORD %token ON %token ONE_SHOT_SYM @@ -5246,11 +5247,14 @@ table_factor: } expr '}' { + LEX *lex= Lex; YYERROR_UNLESS($3 && $7); add_join_on($7,$10); Lex->pop_context(); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; + if (!($$= lex->current_select->nest_last_join(lex->thd))) + YYABORT; } | select_derived_init get_select_lex select_derived2 { @@ -5795,7 +5799,11 @@ select_var_ident: if (lex->result) ((select_dumpvar *)lex->result)->var_list.push_back( new my_var($2,0,0,(enum_field_types)0)); else - YYABORT; + /* + The parser won't create select_result instance only + if it's an EXPLAIN. + */ + DBUG_ASSERT(lex->describe); } | ident_or_text { @@ -5807,10 +5815,8 @@ select_var_ident: my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str); YYABORT; } - if (! lex->result) - YYABORT; - else - { + if (lex->result) + { my_var *var; ((select_dumpvar *)lex->result)-> var_list.push_back(var= new my_var($1,1,t->offset,t->type)); @@ -5818,6 +5824,14 @@ select_var_ident: if (var) var->sp= lex->sphead; #endif + } + else + { + /* + The parser won't create select_result instance only + if it's an EXPLAIN. + */ + DBUG_ASSERT(lex->describe); } } ; @@ -7206,12 +7220,18 @@ simple_ident_q: YYABORT; } + DBUG_ASSERT(!new_row || + (lex->trg_chistics.event == TRG_EVENT_INSERT || + lex->trg_chistics.event == TRG_EVENT_UPDATE)); + const bool read_only= + !(new_row && lex->trg_chistics.action_time == TRG_ACTION_BEFORE); if (!(trg_fld= new Item_trigger_field(Lex->current_context(), new_row ? Item_trigger_field::NEW_ROW: Item_trigger_field::OLD_ROW, $3.str, - Item_trigger_field::AT_READ))) + SELECT_ACL, + read_only))) YYABORT; /* @@ -7847,11 +7867,13 @@ sys_option_value: it= new Item_null(); } + DBUG_ASSERT(lex->trg_chistics.action_time == TRG_ACTION_BEFORE && + (lex->trg_chistics.event == TRG_EVENT_INSERT || + lex->trg_chistics.event == TRG_EVENT_UPDATE)); if (!(trg_fld= new Item_trigger_field(Lex->current_context(), Item_trigger_field::NEW_ROW, $2.base_name.str, - Item_trigger_field::AT_UPDATE) - ) || + UPDATE_ACL, FALSE)) || !(sp_fld= new sp_instr_set_trigger_field(lex->sphead-> instructions(), lex->spcont, diff --git a/sql/table.h b/sql/table.h index ce44f797280..106421d7a17 100644 --- a/sql/table.h +++ b/sql/table.h @@ -221,6 +221,7 @@ struct st_table { ha_rows quick_rows[MAX_KEY]; key_part_map const_key_parts[MAX_KEY]; uint quick_key_parts[MAX_KEY]; + uint quick_n_ranges[MAX_KEY]; /* If this table has TIMESTAMP field with auto-set property (pointed by diff --git a/sql/udf_example.cc b/sql/udf_example.cc index f4f936f34ef..6ad066eacc2 100644 --- a/sql/udf_example.cc +++ b/sql/udf_example.cc @@ -344,7 +344,7 @@ char *metaphon(UDF_INIT *initid, UDF_ARGS *args, char *result, KSflag = 0; /* state flag for KS translation */ for (metaph_end = result + MAXMETAPH, n_start = n; - n <= n_end && result < metaph_end; n++ ) + n < n_end && result < metaph_end; n++ ) { if ( KSflag ) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index fc18f236618..f3cf642e4da 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -246,7 +246,6 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-$PATH}\" \ --with-mysqld-user=%{mysqld_user} \ --with-unix-socket-path=/var/lib/mysql/mysql.sock \ --prefix=/ \ - --with-extra-charsets=complex \ %if %{YASSL_BUILD} --with-yassl \ %endif @@ -305,6 +304,7 @@ then fi BuildMySQL "--enable-shared \ + --with-extra-charsets=all \ --with-berkeley-db \ --with-innodb \ --with-ndbcluster \ @@ -367,6 +367,7 @@ BuildMySQL "--disable-shared \ %else --with-zlib-dir=bundled \ %endif + --with-extra-charsets=complex \ --with-comment=\"MySQL Community Edition - Standard (GPL)\" \ --with-server-suffix='%{server_suffix}' \ --with-archive-storage-engine \ @@ -655,6 +656,7 @@ fi %attr(755, root, root) %{_bindir}/ndb_desc %attr(755, root, root) %{_bindir}/ndb_show_tables %attr(755, root, root) %{_bindir}/ndb_test_platform +%attr(755, root, root) %{_bindir}/ndb_config %files ndb-extra %defattr(-,root,root,0755) @@ -720,6 +722,12 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Wed May 10 2006 Kent Boortz <kent@mysql.com> + +- Use character set "all" for the "max", to make Cluster nodes + independent on the character set directory, and the problem that + two RPM sub packages both wants to install this directory. + * Mon May 01 2006 Kent Boortz <kent@mysql.com> - Use "./libtool --mode=execute" instead of searching for the diff --git a/vio/test-ssl.c b/vio/test-ssl.c index a94eb1a21ff..f8172426e38 100644 --- a/vio/test-ssl.c +++ b/vio/test-ssl.c @@ -57,8 +57,8 @@ main(int argc, char** argv) char* cipher=0; int child_pid,sv[2]; my_bool unused; - struct st_VioSSLAcceptorFd* ssl_acceptor=0; - struct st_VioSSLConnectorFd* ssl_connector=0; + struct st_VioSSLFd* ssl_acceptor= 0; + struct st_VioSSLFd* ssl_connector= 0; Vio* client_vio=0, *server_vio=0; MY_INIT(argv[0]); DBUG_PROCESS(argv[0]); diff --git a/vio/test-sslclient.c b/vio/test-sslclient.c index 3811ba0fb6a..49d6768c884 100644 --- a/vio/test-sslclient.c +++ b/vio/test-sslclient.c @@ -46,7 +46,7 @@ main( int argc __attribute__((unused)), { char client_key[] = "../SSL/client-key.pem", client_cert[] = "../SSL/client-cert.pem"; char ca_file[] = "../SSL/cacert.pem", *ca_path = 0, *cipher=0; - struct st_VioSSLConnectorFd* ssl_connector=0; + struct st_VioSSLFd* ssl_connector= 0; struct sockaddr_in sa; Vio* client_vio=0; int err; diff --git a/vio/test-sslserver.c b/vio/test-sslserver.c index e4d32a75264..daec3a6e6f9 100644 --- a/vio/test-sslserver.c +++ b/vio/test-sslserver.c @@ -44,7 +44,7 @@ fatal_error( const char* r) typedef struct { int sd; - struct st_VioSSLAcceptorFd* ssl_acceptor; + struct st_VioSSLFd* ssl_acceptor; } TH_ARGS; static void @@ -82,7 +82,7 @@ main(int argc __attribute__((unused)), char** argv) char ca_file[] = "../SSL/cacert.pem", *ca_path = 0, *cipher = 0; - struct st_VioSSLAcceptorFd* ssl_acceptor; + struct st_VioSSLFd* ssl_acceptor; pthread_t th; TH_ARGS th_args; diff --git a/vio/vio.c b/vio/vio.c index bc286b2d2bb..2b0a7f0d79b 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -88,19 +88,19 @@ static void vio_init(Vio* vio, enum enum_vio_type type, if (type == VIO_TYPE_SSL) { vio->viodelete =vio_delete; - vio->vioerrno =vio_ssl_errno; + vio->vioerrno =vio_errno; vio->read =vio_ssl_read; vio->write =vio_ssl_write; - vio->fastsend =vio_ssl_fastsend; - vio->viokeepalive =vio_ssl_keepalive; - vio->should_retry =vio_ssl_should_retry; - vio->was_interrupted=vio_ssl_was_interrupted; + vio->fastsend =vio_fastsend; + vio->viokeepalive =vio_keepalive; + vio->should_retry =vio_should_retry; + vio->was_interrupted=vio_was_interrupted; vio->vioclose =vio_ssl_close; - vio->peer_addr =vio_ssl_peer_addr; - vio->in_addr =vio_ssl_in_addr; + vio->peer_addr =vio_peer_addr; + vio->in_addr =vio_in_addr; vio->vioblocking =vio_ssl_blocking; vio->is_blocking =vio_is_blocking; - vio->timeout =vio_ssl_timeout; + vio->timeout =vio_timeout; } else /* default is VIO_TYPE_TCPIP */ #endif /* HAVE_OPENSSL */ @@ -233,3 +233,16 @@ void vio_delete(Vio* vio) my_free((gptr) vio,MYF(0)); } } + + +/* + Cleanup memory allocated by vio or the + components below it when application finish + +*/ +void vio_end(void) +{ +#ifdef HAVE_YASSL + yaSSL_CleanUp(); +#endif +} diff --git a/vio/vio_priv.h b/vio/vio_priv.h index eb495025ddd..db331abdea8 100644 --- a/vio/vio_priv.h +++ b/vio/vio_priv.h @@ -30,28 +30,10 @@ void vio_ignore_timeout(Vio *vio, uint which, uint timeout); int vio_ssl_read(Vio *vio,gptr buf, int size); int vio_ssl_write(Vio *vio,const gptr buf,int size); -void vio_ssl_timeout(Vio *vio, uint which, uint timeout); - -/* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible. */ -int vio_ssl_fastsend(Vio *vio); -/* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible. */ -int vio_ssl_keepalive(Vio *vio, my_bool onoff); -/* Whenever we should retry the last read/write operation. */ -my_bool vio_ssl_should_retry(Vio *vio); -/* Check that operation was timed out */ -my_bool vio_ssl_was_interrupted(Vio *vio); + /* When the workday is over... */ int vio_ssl_close(Vio *vio); -/* Return last error number */ -int vio_ssl_errno(Vio *vio); -my_bool vio_ssl_peer_addr(Vio *vio, char *buf, uint16 *port); -void vio_ssl_in_addr(Vio *vio, struct in_addr *in); + int vio_ssl_blocking(Vio *vio, my_bool set_blocking_mode, my_bool *old_mode); -/* Single copy for server */ -enum vio_ssl_acceptorfd_state -{ - state_connect = 1, - state_accept = 2 -}; #endif /* HAVE_OPENSSL */ diff --git a/vio/viossl.c b/vio/viossl.c index 1273814c551..e869493c604 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -51,384 +51,240 @@ static int SSL_set_fd_bsd(SSL *s, int fd) static void -report_errors() +report_errors(SSL* ssl) { unsigned long l; - const char* file; - const char* data; - int line,flags; + const char *file; + const char *data; + int line, flags; +#ifndef DBUG_OFF + char buf[512]; +#endif + DBUG_ENTER("report_errors"); - while ((l=ERR_get_error_line_data(&file,&line,&data,&flags))) + while ((l= ERR_get_error_line_data(&file,&line,&data,&flags))) { - char buf[512]; DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf), file,line,(flags&ERR_TXT_STRING)?data:"")) ; } - DBUG_PRINT("info", ("errno: %d", socket_errno)); - DBUG_VOID_RETURN; -} + if (ssl) + DBUG_PRINT("error", ("error: %s", + ERR_error_string(SSL_get_error(ssl, l), buf))); -int vio_ssl_errno(Vio *vio __attribute__((unused))) -{ - return socket_errno; /* On Win32 this mapped to WSAGetLastError() */ + DBUG_PRINT("info", ("socket_errno: %d", socket_errno)); + DBUG_VOID_RETURN; } -int vio_ssl_read(Vio * vio, gptr buf, int size) +int vio_ssl_read(Vio *vio, gptr buf, int size) { int r; DBUG_ENTER("vio_ssl_read"); DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d, ssl_: 0x%p", vio->sd, buf, size, vio->ssl_arg)); - if ((r= SSL_read((SSL*) vio->ssl_arg, buf, size)) < 0) - { - int err= SSL_get_error((SSL*) vio->ssl_arg, r); - DBUG_PRINT("error",("SSL_read(): %d SSL_get_error(): %d", r, err)); - report_errors(); - } + r= SSL_read((SSL*) vio->ssl_arg, buf, size); +#ifndef DBUG_OFF + if (r < 0) + report_errors((SSL*) vio->ssl_arg); +#endif DBUG_PRINT("exit", ("%d", r)); DBUG_RETURN(r); } -int vio_ssl_write(Vio * vio, const gptr buf, int size) +int vio_ssl_write(Vio *vio, const gptr buf, int size) { int r; DBUG_ENTER("vio_ssl_write"); DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size)); - if ((r= SSL_write((SSL*) vio->ssl_arg, buf, size)) < 0) - report_errors(); - DBUG_PRINT("exit", ("%d", r)); - DBUG_RETURN(r); -} - - -int vio_ssl_fastsend(Vio * vio __attribute__((unused))) -{ - int r=0; - DBUG_ENTER("vio_ssl_fastsend"); - -#if defined(IPTOS_THROUGHPUT) && !defined(__EMX__) - { - int tos= IPTOS_THROUGHPUT; - r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)); - } -#endif /* IPTOS_THROUGHPUT && !__EMX__ */ - if (!r) - { -#ifdef __WIN__ - BOOL nodelay= 1; - r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (const char*) &nodelay, - sizeof(nodelay)); -#else - int nodelay= 1; - r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay, - sizeof(nodelay)); -#endif /* __WIN__ */ - } - if (r) - { - DBUG_PRINT("warning", ("Couldn't set socket option for fast send")); - r= -1; - } + r= SSL_write((SSL*) vio->ssl_arg, buf, size); +#ifndef DBUG_OFF + if (r < 0) + report_errors((SSL*) vio->ssl_arg); +#endif DBUG_PRINT("exit", ("%d", r)); DBUG_RETURN(r); } -int vio_ssl_keepalive(Vio* vio, my_bool set_keep_alive) +int vio_ssl_close(Vio *vio) { - int r=0; - DBUG_ENTER("vio_ssl_keepalive"); - DBUG_PRINT("enter", ("sd: %d, set_keep_alive: %d", vio->sd, (int) - set_keep_alive)); - if (vio->type != VIO_TYPE_NAMEDPIPE) - { - uint opt = (set_keep_alive) ? 1 : 0; - r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, - sizeof(opt)); - } - DBUG_RETURN(r); -} - - -my_bool -vio_ssl_should_retry(Vio * vio __attribute__((unused))) -{ - int en = socket_errno; - return (en == SOCKET_EAGAIN || en == SOCKET_EINTR || - en == SOCKET_EWOULDBLOCK); -} - - -my_bool -vio_ssl_was_interrupted(Vio *vio __attribute__((unused))) -{ - int en= socket_errno; - return (en == SOCKET_EAGAIN || en == SOCKET_EINTR || - en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT); -} - - -int vio_ssl_close(Vio * vio) -{ - int r; + int r= 0; + SSL *ssl= (SSL*)vio->ssl_arg; DBUG_ENTER("vio_ssl_close"); - r=0; - if ((SSL*) vio->ssl_arg) - { - r = SSL_shutdown((SSL*) vio->ssl_arg); - SSL_free((SSL*) vio->ssl_arg); - vio->ssl_arg= 0; - } - if (vio->sd >= 0) - { - if (shutdown(vio->sd, 2)) - r= -1; - if (closesocket(vio->sd)) - r= -1; - } - if (r) - { - DBUG_PRINT("error", ("close() failed, error: %d",socket_errno)); - report_errors(); - /* FIXME: error handling (not critical for MySQL) */ - } - vio->type= VIO_CLOSED; - vio->sd= -1; - DBUG_RETURN(r); -} - -const char *vio_ssl_description(Vio * vio) -{ - return vio->desc; -} - -enum enum_vio_type vio_ssl_type(Vio* vio) -{ - return vio->type; -} - -my_socket vio_ssl_fd(Vio* vio) -{ - return vio->sd; -} - - -my_bool vio_ssl_peer_addr(Vio * vio, char *buf, uint16 *port) -{ - DBUG_ENTER("vio_ssl_peer_addr"); - DBUG_PRINT("enter", ("sd: %d", vio->sd)); - if (vio->localhost) - { - strmov(buf,"127.0.0.1"); - *port=0; - } - else + if (ssl) { - size_socket addrLen = sizeof(struct sockaddr); - if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)), - &addrLen) != 0) + switch ((r= SSL_shutdown(ssl))) { - DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno)); - DBUG_RETURN(1); + case 1: /* Shutdown successful */ + break; + case 0: /* Shutdown not yet finished, call it again */ + if ((r= SSL_shutdown(ssl) >= 0)) + break; + /* Fallthrough */ + default: /* Shutdown failed */ + DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %s", + SSL_get_error(ssl, r))); + break; } -#ifdef TO_BE_FIXED - my_inet_ntoa(vio->remote.sin_addr,buf); - *port= 0; -#else - strmov(buf, "unknown"); - *port= 0; -#endif + SSL_free(ssl); + vio->ssl_arg= 0; } - DBUG_PRINT("exit", ("addr: %s", buf)); - DBUG_RETURN(0); + DBUG_RETURN(vio_close(vio)); } -void vio_ssl_in_addr(Vio *vio, struct in_addr *in) +int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout) { - DBUG_ENTER("vio_ssl_in_addr"); - if (vio->localhost) - bzero((char*) in, sizeof(*in)); - else - *in=vio->remote.sin_addr; - DBUG_VOID_RETURN; -} - - -/* - TODO: Add documentation -*/ - -int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout) -{ - char *str; - char buf[1024]; - X509* client_cert; + SSL *ssl; my_bool unused; my_bool net_blocking; enum enum_vio_type old_type; DBUG_ENTER("sslaccept"); - DBUG_PRINT("enter", ("sd: %d ptr: Ox%p, timeout: %d", + DBUG_PRINT("enter", ("sd: %d ptr: %p, timeout: %d", vio->sd, ptr, timeout)); old_type= vio->type; - net_blocking = vio_is_blocking(vio); + net_blocking= vio_is_blocking(vio); vio_blocking(vio, 1, &unused); /* Must be called before reset */ - vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE); - vio->ssl_arg= 0; - if (!(vio->ssl_arg= (void*) SSL_new(ptr->ssl_context))) + vio_reset(vio, VIO_TYPE_SSL, vio->sd, 0, FALSE); + + if (!(ssl= SSL_new(ptr->ssl_context))) { DBUG_PRINT("error", ("SSL_new failure")); - report_errors(); + report_errors(ssl); vio_reset(vio, old_type,vio->sd,0,FALSE); vio_blocking(vio, net_blocking, &unused); DBUG_RETURN(1); } - DBUG_PRINT("info", ("ssl_: Ox%p timeout: %ld", - (SSL*) vio->ssl_arg, timeout)); - SSL_clear((SSL*) vio->ssl_arg); - SSL_SESSION_set_timeout(SSL_get_session((SSL*) vio->ssl_arg), timeout); - SSL_set_fd((SSL*) vio->ssl_arg,vio->sd); - SSL_set_accept_state((SSL*) vio->ssl_arg); - if (SSL_do_handshake((SSL*) vio->ssl_arg) < 1) + vio->ssl_arg= (void*)ssl; + DBUG_PRINT("info", ("ssl_: %p timeout: %ld", ssl, timeout)); + SSL_clear(ssl); + SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); + SSL_set_fd(ssl, vio->sd); + SSL_set_accept_state(ssl); + if (SSL_do_handshake(ssl) < 1) { DBUG_PRINT("error", ("SSL_do_handshake failure")); - report_errors(); - SSL_free((SSL*) vio->ssl_arg); + report_errors(ssl); + SSL_free(ssl); vio->ssl_arg= 0; vio_reset(vio, old_type,vio->sd,0,FALSE); vio_blocking(vio, net_blocking, &unused); DBUG_RETURN(1); } + #ifndef DBUG_OFF - DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'" - ,SSL_get_cipher_name((SSL*) vio->ssl_arg))); - client_cert = SSL_get_peer_certificate ((SSL*) vio->ssl_arg); - if (client_cert != NULL) { - DBUG_PRINT("info",("Client certificate:")); - str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0); - DBUG_PRINT("info",("\t subject: %s", str)); - free (str); + char buf[1024]; + X509 *client_cert; + DBUG_PRINT("info",("cipher_name= '%s'", SSL_get_cipher_name(ssl))); - str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0); - DBUG_PRINT("info",("\t issuer: %s", str)); - free (str); + if ((client_cert= SSL_get_peer_certificate (ssl))) + { + DBUG_PRINT("info",("Client certificate:")); + X509_NAME_oneline (X509_get_subject_name (client_cert), + buf, sizeof(buf)); + DBUG_PRINT("info",("\t subject: %s", buf)); - X509_free (client_cert); - } - else - DBUG_PRINT("info",("Client does not have certificate.")); + X509_NAME_oneline (X509_get_issuer_name (client_cert), + buf, sizeof(buf)); + DBUG_PRINT("info",("\t issuer: %s", buf)); - str=SSL_get_shared_ciphers((SSL*) vio->ssl_arg, buf, sizeof(buf)); - if (str) - { - DBUG_PRINT("info",("SSL_get_shared_ciphers() returned '%s'",str)); - } - else - { - DBUG_PRINT("info",("no shared ciphers!")); - } + X509_free (client_cert); + } + else + DBUG_PRINT("info",("Client does not have certificate.")); + if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf))) + { + DBUG_PRINT("info",("shared_ciphers: '%s'", buf)); + } + else + DBUG_PRINT("info",("no shared ciphers!")); + } #endif + DBUG_RETURN(0); } -int sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout) +int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout) { - char *str; - X509* server_cert; + SSL *ssl; my_bool unused; my_bool net_blocking; - enum enum_vio_type old_type; + enum enum_vio_type old_type; + DBUG_ENTER("sslconnect"); - DBUG_PRINT("enter", ("sd: %d ptr: 0x%p ctx: 0x%p", - vio->sd,ptr,ptr->ssl_context)); + DBUG_PRINT("enter", ("sd: %d, ptr: %p, ctx: %p", + vio->sd, ptr, ptr->ssl_context)); old_type= vio->type; - net_blocking = vio_is_blocking(vio); + net_blocking= vio_is_blocking(vio); vio_blocking(vio, 1, &unused); /* Must be called before reset */ - vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE); - vio->ssl_arg= 0; - if (!(vio->ssl_arg = SSL_new(ptr->ssl_context))) + vio_reset(vio, VIO_TYPE_SSL, vio->sd, 0, FALSE); + if (!(ssl= SSL_new(ptr->ssl_context))) { DBUG_PRINT("error", ("SSL_new failure")); - report_errors(); - vio_reset(vio, old_type,vio->sd,0,FALSE); - vio_blocking(vio, net_blocking, &unused); + report_errors(ssl); + vio_reset(vio, old_type, vio->sd, 0, FALSE); + vio_blocking(vio, net_blocking, &unused); DBUG_RETURN(1); } - DBUG_PRINT("info", ("ssl_: 0x%p timeout: %ld", - (SSL*) vio->ssl_arg, timeout)); - SSL_clear((SSL*) vio->ssl_arg); - SSL_SESSION_set_timeout(SSL_get_session((SSL*) vio->ssl_arg), timeout); - SSL_set_fd ((SSL*) vio->ssl_arg, vio_ssl_fd(vio)); - SSL_set_connect_state((SSL*) vio->ssl_arg); - if (SSL_do_handshake((SSL*) vio->ssl_arg) < 1) + vio->ssl_arg= (void*)ssl; + DBUG_PRINT("info", ("ssl: %p, timeout: %ld", ssl, timeout)); + SSL_clear(ssl); + SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); + SSL_set_fd(ssl, vio->sd); + SSL_set_connect_state(ssl); + if (SSL_do_handshake(ssl) < 1) { DBUG_PRINT("error", ("SSL_do_handshake failure")); - report_errors(); - SSL_free((SSL*) vio->ssl_arg); + report_errors(ssl); + SSL_free(ssl); vio->ssl_arg= 0; - vio_reset(vio, old_type,vio->sd,0,FALSE); + vio_reset(vio, old_type, vio->sd, 0, FALSE); vio_blocking(vio, net_blocking, &unused); DBUG_RETURN(1); - } + } #ifndef DBUG_OFF - DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'" - ,SSL_get_cipher_name((SSL*) vio->ssl_arg))); - server_cert = SSL_get_peer_certificate ((SSL*) vio->ssl_arg); - if (server_cert != NULL) { - DBUG_PRINT("info",("Server certificate:")); - str = X509_NAME_oneline (X509_get_subject_name (server_cert), 0, 0); - DBUG_PRINT("info",("\t subject: %s", str)); - free(str); - - str = X509_NAME_oneline (X509_get_issuer_name (server_cert), 0, 0); - DBUG_PRINT("info",("\t issuer: %s", str)); - free(str); - - /* - We could do all sorts of certificate verification stuff here before - deallocating the certificate. - */ - X509_free (server_cert); + X509 *server_cert; + DBUG_PRINT("info",("cipher_name: '%s'" , SSL_get_cipher_name(ssl))); + + if ((server_cert= SSL_get_peer_certificate (ssl))) + { + char buf[256]; + DBUG_PRINT("info",("Server certificate:")); + X509_NAME_oneline(X509_get_subject_name(server_cert), buf, sizeof(buf)); + DBUG_PRINT("info",("\t subject: %s", buf)); + X509_NAME_oneline (X509_get_issuer_name(server_cert), buf, sizeof(buf)); + DBUG_PRINT("info",("\t issuer: %s", buf)); + X509_free (server_cert); + } + else + DBUG_PRINT("info",("Server does not have certificate.")); } - else - DBUG_PRINT("info",("Server does not have certificate.")); #endif + DBUG_RETURN(0); } -int vio_ssl_blocking(Vio * vio __attribute__((unused)), +int vio_ssl_blocking(Vio *vio __attribute__((unused)), my_bool set_blocking_mode, my_bool *old_mode) { + /* Mode is always blocking */ + *old_mode= 1; /* Return error if we try to change to non_blocking mode */ - *old_mode=1; /* Mode is always blocking */ - return set_blocking_mode ? 0 : 1; + return (set_blocking_mode ? 0 : 1); } - -void vio_ssl_timeout(Vio *vio __attribute__((unused)), - uint which __attribute__((unused)), - uint timeout __attribute__((unused))) -{ -#ifdef __WIN__ - ulong wait_timeout= (ulong) timeout * 1000; - (void) setsockopt(vio->sd, SOL_SOCKET, - which ? SO_SNDTIMEO : SO_RCVTIMEO, (char*) &wait_timeout, - sizeof(wait_timeout)); -#endif /* __WIN__ */ -} #endif /* HAVE_OPENSSL */ diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 4ee27f1e491..2c528e9a2fc 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -21,7 +21,6 @@ static bool ssl_algorithms_added = FALSE; static bool ssl_error_strings_loaded= FALSE; static int verify_depth = 0; -static int verify_error = X509_V_OK; static unsigned char dh512_p[]= { @@ -82,30 +81,31 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file) DBUG_ENTER("vio_set_cert_stuff"); DBUG_PRINT("enter", ("ctx: %p, cert_file: %s, key_file: %s", ctx, cert_file, key_file)); - if (cert_file != NULL) + if (cert_file) { - if (SSL_CTX_use_certificate_file(ctx,cert_file,SSL_FILETYPE_PEM) <= 0) + if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0) { - DBUG_PRINT("error",("unable to get certificate from '%s'\n",cert_file)); + DBUG_PRINT("error",("unable to get certificate from '%s'\n", cert_file)); /* FIX stderr */ fprintf(stderr,"Error when connection to server using SSL:"); ERR_print_errors_fp(stderr); fprintf(stderr,"Unable to get certificate from '%s'\n", cert_file); fflush(stderr); - DBUG_RETURN(0); + DBUG_RETURN(1); } - if (key_file == NULL) - key_file = cert_file; - if (SSL_CTX_use_PrivateKey_file(ctx,key_file, - SSL_FILETYPE_PEM) <= 0) + + if (!key_file) + key_file= cert_file; + + if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) { - DBUG_PRINT("error", ("unable to get private key from '%s'\n",key_file)); + DBUG_PRINT("error", ("unable to get private key from '%s'\n", key_file)); /* FIX stderr */ fprintf(stderr,"Error when connection to server using SSL:"); ERR_print_errors_fp(stderr); - fprintf(stderr,"Unable to get private key from '%s'\n", cert_file); - fflush(stderr); - DBUG_RETURN(0); + fprintf(stderr,"Unable to get private key from '%s'\n", key_file); + fflush(stderr); + DBUG_RETURN(1); } /* @@ -116,45 +116,45 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file) { DBUG_PRINT("error", ("Private key does not match the certificate public key\n")); - DBUG_RETURN(0); + DBUG_RETURN(1); } } - DBUG_RETURN(1); + DBUG_RETURN(0); } static int vio_verify_callback(int ok, X509_STORE_CTX *ctx) { - char buf[256]; - X509* err_cert; - int err,depth; + char buf[256]; + X509 *err_cert; DBUG_ENTER("vio_verify_callback"); - DBUG_PRINT("enter", ("ok: %d, ctx: 0x%p", ok, ctx)); - err_cert=X509_STORE_CTX_get_current_cert(ctx); - err= X509_STORE_CTX_get_error(ctx); - depth= X509_STORE_CTX_get_error_depth(ctx); + DBUG_PRINT("enter", ("ok: %d, ctx: %p", ok, ctx)); - X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buf)); + err_cert= X509_STORE_CTX_get_current_cert(ctx); + X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); + DBUG_PRINT("info", ("cert: %s", buf)); if (!ok) { - DBUG_PRINT("error",("verify error: num: %d : '%s'\n",err, + int err, depth; + err= X509_STORE_CTX_get_error(ctx); + depth= X509_STORE_CTX_get_error_depth(ctx); + + DBUG_PRINT("error",("verify error: %d, '%s'",err, X509_verify_cert_error_string(err))); + /* + Approve cert if depth is greater then "verify_depth", currently + verify_depth is always 0 and there is no way to increase it. + */ if (verify_depth >= depth) - { - ok=1; - verify_error=X509_V_OK; - } - else - { - verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG; - } + ok= 1; } - switch (ctx->error) { + switch (ctx->error) + { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256); - DBUG_PRINT("info",("issuer= %s\n",buf)); + X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256); + DBUG_PRINT("info",("issuer= %s\n", buf)); break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: @@ -198,193 +198,150 @@ static void netware_ssl_init() #endif /* __NETWARE__ */ -/************************ VioSSLConnectorFd **********************************/ -/* - TODO: - Add option --verify to mysql to be able to change verification mode -*/ - -struct st_VioSSLConnectorFd * -new_VioSSLConnectorFd(const char* key_file, - const char* cert_file, - const char* ca_file, - const char* ca_path, - const char* cipher) +static void check_ssl_init() { - int verify = SSL_VERIFY_NONE; - struct st_VioSSLConnectorFd* ptr; - int result; - DH *dh; - DBUG_ENTER("new_VioSSLConnectorFd"); - - if (!(ptr=((struct st_VioSSLConnectorFd*) - my_malloc(sizeof(struct st_VioSSLConnectorFd),MYF(0))))) - DBUG_RETURN(0); - - ptr->ssl_context= 0; - ptr->ssl_method= 0; - /* FIXME: constants! */ - if (!ssl_algorithms_added) { - DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()")); - ssl_algorithms_added = TRUE; + ssl_algorithms_added= TRUE; SSL_library_init(); OpenSSL_add_all_algorithms(); + } + #ifdef __NETWARE__ netware_ssl_init(); #endif if (!ssl_error_strings_loaded) { - DBUG_PRINT("info", ("todo:SSL_load_error_strings()")); - ssl_error_strings_loaded = TRUE; + ssl_error_strings_loaded= TRUE; SSL_load_error_strings(); } - ptr->ssl_method = TLSv1_client_method(); - ptr->ssl_context = SSL_CTX_new(ptr->ssl_method); - DBUG_PRINT("info", ("ssl_context: %p",ptr->ssl_context)); - if (ptr->ssl_context == 0) +} + +/************************ VioSSLFd **********************************/ +static struct st_VioSSLFd * +new_VioSSLFd(const char *key_file, const char *cert_file, + const char *ca_file, const char *ca_path, + const char *cipher, SSL_METHOD *method) +{ + DH *dh; + struct st_VioSSLFd *ssl_fd; + DBUG_ENTER("new_VioSSLFd"); + + check_ssl_init(); + + if (!(ssl_fd= ((struct st_VioSSLFd*) + my_malloc(sizeof(struct st_VioSSLFd),MYF(0))))) + DBUG_RETURN(0); + + if (!(ssl_fd->ssl_context= SSL_CTX_new(method))) { DBUG_PRINT("error", ("SSL_CTX_new failed")); report_errors(); - goto ctor_failure; - } - /* - SSL_CTX_set_options - SSL_CTX_set_info_callback - */ - if (cipher) - { - result=SSL_CTX_set_cipher_list(ptr->ssl_context, cipher); - DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result)); + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); } - SSL_CTX_set_verify(ptr->ssl_context, verify, vio_verify_callback); - if (vio_set_cert_stuff(ptr->ssl_context, cert_file, key_file) == -1) + + /* Set the ciphers that can be used */ + if (cipher && SSL_CTX_set_cipher_list(ssl_fd->ssl_context, cipher)) { - DBUG_PRINT("error", ("vio_set_cert_stuff failed")); + DBUG_PRINT("error", ("failed to set ciphers to use")); report_errors(); - goto ctor_failure; + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); } - if (SSL_CTX_load_verify_locations( ptr->ssl_context, ca_file,ca_path) == 0) + + /* Load certs from the trusted ca */ + if (SSL_CTX_load_verify_locations(ssl_fd->ssl_context, ca_file, ca_path) == 0) { DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed")); - if (SSL_CTX_set_default_verify_paths(ptr->ssl_context) == 0) + if (SSL_CTX_set_default_verify_paths(ssl_fd->ssl_context) == 0) { DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed")); report_errors(); - goto ctor_failure; + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); } - } + } + + if (vio_set_cert_stuff(ssl_fd->ssl_context, cert_file, key_file)) + { + DBUG_PRINT("error", ("vio_set_cert_stuff failed")); + report_errors(); + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); + } /* DH stuff */ dh=get_dh512(); - SSL_CTX_set_tmp_dh(ptr->ssl_context,dh); + SSL_CTX_set_tmp_dh(ssl_fd->ssl_context, dh); DH_free(dh); - DBUG_RETURN(ptr); -ctor_failure: - DBUG_PRINT("exit", ("there was an error")); - my_free((gptr)ptr,MYF(0)); - DBUG_RETURN(0); + DBUG_PRINT("exit", ("OK 1")); + + DBUG_RETURN(ssl_fd); } -/************************ VioSSLAcceptorFd **********************************/ -/* - TODO: - Add option --verify to mysqld to be able to change verification mode -*/ -struct st_VioSSLAcceptorFd* -new_VioSSLAcceptorFd(const char *key_file, - const char *cert_file, - const char *ca_file, - const char *ca_path, - const char *cipher) +/************************ VioSSLConnectorFd **********************************/ +struct st_VioSSLFd * +new_VioSSLConnectorFd(const char *key_file, const char *cert_file, + const char *ca_file, const char *ca_path, + const char *cipher) { - int verify = (SSL_VERIFY_PEER | - SSL_VERIFY_CLIENT_ONCE); - struct st_VioSSLAcceptorFd* ptr; - int result; - DH *dh; - DBUG_ENTER("new_VioSSLAcceptorFd"); + struct st_VioSSLFd *ssl_fd; + int verify= SSL_VERIFY_PEER; + if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, + ca_path, cipher, TLSv1_client_method()))) + { + return 0; + } - ptr= ((struct st_VioSSLAcceptorFd*) - my_malloc(sizeof(struct st_VioSSLAcceptorFd),MYF(0))); - ptr->ssl_context=0; - ptr->ssl_method=0; - /* FIXME: constants! */ - ptr->session_id_context= ptr; + /* Init the VioSSLFd as a "connector" ie. the client side */ - if (!ssl_algorithms_added) - { - DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()")); - ssl_algorithms_added = TRUE; - SSL_library_init(); - OpenSSL_add_all_algorithms(); + /* + The verify_callback function is used to control the behaviour + when the SSL_VERIFY_PEER flag is set. + */ + SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback); - } -#ifdef __NETWARE__ - netware_ssl_init(); -#endif + return ssl_fd; +} - if (!ssl_error_strings_loaded) - { - DBUG_PRINT("info", ("todo: SSL_load_error_strings()")); - ssl_error_strings_loaded = TRUE; - SSL_load_error_strings(); - } - ptr->ssl_method= TLSv1_server_method(); - ptr->ssl_context= SSL_CTX_new(ptr->ssl_method); - if (ptr->ssl_context == 0) - { - DBUG_PRINT("error", ("SSL_CTX_new failed")); - report_errors(); - goto ctor_failure; - } - if (cipher) + +/************************ VioSSLAcceptorFd **********************************/ +struct st_VioSSLFd* +new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, + const char *ca_file, const char *ca_path, + const char *cipher) +{ + struct st_VioSSLFd *ssl_fd; + int verify= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; + if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, + ca_path, cipher, TLSv1_server_method()))) { - result=SSL_CTX_set_cipher_list(ptr->ssl_context, cipher); - DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result)); + return 0; } - /* SSL_CTX_set_quiet_shutdown(ctx,1); */ - SSL_CTX_sess_set_cache_size(ptr->ssl_context,128); + /* Init the the VioSSLFd as a "acceptor" ie. the server side */ - /* DH? */ - SSL_CTX_set_verify(ptr->ssl_context, verify, vio_verify_callback); - SSL_CTX_set_session_id_context(ptr->ssl_context, - (const uchar*) &(ptr->session_id_context), - sizeof(ptr->session_id_context)); + /* Set max number of cached sessions, returns the previous size */ + SSL_CTX_sess_set_cache_size(ssl_fd->ssl_context, 128); /* - SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile)); + The verify_callback function is used to control the behaviour + when the SSL_VERIFY_PEER flag is set. */ - if (vio_set_cert_stuff(ptr->ssl_context, cert_file, key_file) == -1) - { - DBUG_PRINT("error", ("vio_set_cert_stuff failed")); - report_errors(); - goto ctor_failure; - } - if (SSL_CTX_load_verify_locations( ptr->ssl_context, ca_file, ca_path) == 0) - { - DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed")); - if (SSL_CTX_set_default_verify_paths(ptr->ssl_context)==0) - { - DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed")); - report_errors(); - goto ctor_failure; - } - } - /* DH stuff */ - dh=get_dh512(); - SSL_CTX_set_tmp_dh(ptr->ssl_context,dh); - DH_free(dh); - DBUG_RETURN(ptr); + SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback); -ctor_failure: - DBUG_PRINT("exit", ("there was an error")); - my_free((gptr) ptr,MYF(0)); - DBUG_RETURN(0); + /* + Set session_id - an identifier for this server session + Use the ssl_fd pointer + */ + SSL_CTX_set_session_id_context(ssl_fd->ssl_context, + (const unsigned char *)ssl_fd, + sizeof(ssl_fd)); + + return ssl_fd; } #endif /* HAVE_OPENSSL */ |